17 #ifndef THRILL_MEM_ALIGNED_ALLOCATOR_HEADER 18 #define THRILL_MEM_ALIGNED_ALLOCATOR_HEADER 27 #define THRILL_DEFAULT_ALIGN 4096 32 template <
typename MustBeInt>
37 template <
typename MustBeInt>
40 template <
typename Type = char,
41 typename BaseAllocator = std::allocator<char>,
45 static constexpr
bool debug =
false;
47 static_assert(
sizeof(
typename BaseAllocator::value_type) == 1,
48 "BaseAllocator must be a char/byte allocator");
74 template <
typename OtherType>
76 : base_(other.base()) { }
85 if (n > this->max_size())
86 throw std::bad_alloc();
88 return static_cast<pointer>(allocate_bytes(n *
sizeof(
Type)));
94 deallocate_bytes(p, n *
sizeof(
Type));
98 template <
typename Other>
100 return (base_ == other.base_);
104 template <
typename Other>
106 return (base_ != other.base_);
111 void * allocate_bytes(
size_t size,
size_t meta_info_size = 0);
112 void deallocate_bytes(
void* ptr,
size_t size,
size_t meta_info_size = 0) noexcept;
114 const BaseAllocator&
base()
const {
return base_; }
132 template <
typename Type,
typename BaseAllocator,
size_t Alignment>
134 size_t size,
size_t meta_info_size) {
136 LOG <<
"aligned_alloc<" << Alignment <<
">(), size = " << size
137 <<
", meta info size = " << meta_info_size;
144 size_t alloc_size = Alignment +
sizeof(
char*) + meta_info_size + size;
145 char* buffer =
reinterpret_cast<char*
>(base_.allocate(alloc_size));
147 if (buffer ==
nullptr)
150 char* reserve_buffer = buffer +
sizeof(
char*) + meta_info_size;
151 char* result = reserve_buffer + Alignment -
152 (((size_t)reserve_buffer) % (Alignment)) - meta_info_size;
154 LOG <<
"aligned_alloc<" << Alignment <<
">() address " <<
static_cast<void*
>(result)
155 <<
" lost " << (result - buffer) <<
" bytes";
160 assert(
long(result - buffer) >=
long(
sizeof(
char*)));
165 size_t realloc_size = (result - buffer) + meta_info_size + size;
167 char* realloced =
static_cast<char*
>(
std::realloc(buffer, realloc_size));
168 if (buffer != realloced) {
171 LOG1 <<
"mem::aligned_alloc: disabling realloc()";
174 return allocate(size, meta_info_size);
176 assert(result + size <= buffer + realloc_size);
180 *((
reinterpret_cast<char**
>(result)) - 1) = buffer;
181 LOG <<
"aligned_alloc<" << Alignment <<
">(), allocated at " 182 <<
static_cast<void*
>(buffer) <<
" returning " << static_cast<void*>(result);
183 LOG <<
"aligned_alloc<" << Alignment <<
">(size = " << size
184 <<
", meta info size = " << meta_info_size
185 <<
") => buffer = " <<
static_cast<void*
>(buffer)
186 <<
", ptr = " << static_cast<void*>(result);
191 template <
typename Type,
typename BaseAllocator,
size_t Alignment>
193 void* ptr,
size_t size,
size_t meta_info_size) noexcept {
196 char* buffer = *((
reinterpret_cast<char**
>(ptr)) - 1);
197 size_t alloc_size = Alignment +
sizeof(
char*) + meta_info_size + size;
198 LOG0 <<
"aligned_dealloc<" << Alignment <<
">(), ptr = " << ptr
199 <<
", buffer = " <<
static_cast<void*
>(buffer);
200 base_.deallocate(buffer, alloc_size);
219 #endif // !THRILL_MEM_ALIGNED_ALLOCATOR_HEADER void deallocate_bytes(void *ptr, size_t size, size_t meta_info_size=0) noexcept
static bool may_use_realloc_
static void * aligned_alloc(size_t size, size_t meta_info_size=0)
#define LOG0
Override default output: never or always output log.
const Byte * const_pointer
std::ptrdiff_t difference_type
void * allocate_bytes(size_t size, size_t meta_info_size=0)
#define THRILL_DEFAULT_ALIGN
AlignedAllocator(const BaseAllocator &base=BaseAllocator())
Construct with base allocator.
const BaseAllocator & base() const
std::false_type is_always_equal
C++11 type flag.
static constexpr bool debug
bool operator==(const uint_pair &b) const
equality checking operator
static void aligned_dealloc(void *ptr, size_t size, size_t meta_info_size=0)
BaseAllocator base_
base allocator
pointer allocate(size_type n, const void *=nullptr)
void free(void *ptr) NOEXCEPT
exported free symbol that overrides loading from libc
#define LOG
Default logging method: output if the local debug variable is true.
AlignedAllocator(const AlignedAllocator< OtherType > &other) noexcept
copy-constructor from a rebound allocator
void * realloc(void *ptr, size_t size) NOEXCEPT
exported realloc() symbol that overrides loading from libc
void deallocate(pointer p, size_type n) noexcept
const Byte & const_reference
Return allocator for different type.
bool operator!=(const uint_pair &b) const
inequality checking operator