Avoid using ATOMIC_INIT
[openal-soft.git] / common / almalloc.h
blobd9b285fe91d71e54eedcad81c3cd15800a9f0c87
1 #ifndef AL_MALLOC_H
2 #define AL_MALLOC_H
4 #include <stddef.h>
6 #include <memory>
7 #include <limits>
9 /* Minimum alignment required by posix_memalign. */
10 #define DEF_ALIGN sizeof(void*)
12 void *al_malloc(size_t alignment, size_t size);
13 void *al_calloc(size_t alignment, size_t size);
14 void al_free(void *ptr) noexcept;
16 size_t al_get_page_size(void) noexcept;
18 /**
19 * Returns non-0 if the allocation function has direct alignment handling.
20 * Otherwise, the standard malloc is used with an over-allocation and pointer
21 * offset strategy.
23 int al_is_sane_alignment_allocator(void) noexcept;
25 #define DEF_NEWDEL(T) \
26 void *operator new(size_t size) \
27 { \
28 void *ret = al_malloc(alignof(T), size); \
29 if(!ret) throw std::bad_alloc(); \
30 return ret; \
31 } \
32 void operator delete(void *block) noexcept { al_free(block); }
34 #define DEF_PLACE_NEWDEL() \
35 void *operator new(size_t /*size*/, void *ptr) noexcept { return ptr; } \
36 void operator delete(void *block) noexcept { al_free(block); }
38 namespace al {
40 template<typename T, size_t alignment=DEF_ALIGN>
41 struct allocator : public std::allocator<T> {
42 using size_type = size_t;
43 using pointer = T*;
44 using const_pointer = const T*;
46 template<typename U>
47 struct rebind {
48 using other = allocator<U, alignment>;
51 pointer allocate(size_type n, const void* = nullptr)
53 if(n > std::numeric_limits<size_t>::max() / sizeof(T))
54 throw std::bad_alloc();
56 void *ret{al_malloc(alignment, n*sizeof(T))};
57 if(!ret) throw std::bad_alloc();
58 return static_cast<pointer>(ret);
61 void deallocate(pointer p, size_type)
62 { al_free(p); }
64 allocator() : std::allocator<T>() { }
65 allocator(const allocator &a) : std::allocator<T>(a) { }
66 template<class U>
67 allocator(const allocator<U,alignment> &a) : std::allocator<T>(a)
68 { }
71 } // namespace al
73 #endif /* AL_MALLOC_H */