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