Quantcast
Channel: GameDev.net
Viewing all articles
Browse latest Browse all 17825

Custom C++ allocator for alligned data

$
0
0
I am a bit confused about writing a custom allocator for aligned data. My aligned structs/classes typically derive AlignedData (passing the struct/class name as class template argument). The latter provides a custom operator new/new[]/delete/delete[]. I now want to write a custom allocator for these aligned structs, but I am confused about allocate/deallocate vs construct/destroy. General #include <malloc.h> inline void *AllocAligned(size_t size, size_t alignment = 16) noexcept { return _aligned_malloc(size, alignment); } template < typename DataT > inline DataT *AllocAligned(size_t count) noexcept { return static_cast< DataT * >(AllocAligned(count * sizeof(DataT))); } inline void FreeAligned(void *ptr) noexcept { if (!ptr) { return; } _aligned_free(ptr); } AlignedData template< typename DataT > struct AlignedData { public: static void *operator new(size_t size) { const size_t alignment = __alignof(DataT); // __declspec(align) on DataT is required static_assert(alignment > 8, "AlignedData is only useful for types with > 8 byte alignment."); void * const ptr = AllocAligned(size, alignment); if (!ptr) { throw std::bad_alloc(); } return ptr; } static void operator delete(void *ptr) noexcept { FreeAligned(ptr); } static void *operator new[](size_t size) { return operator new(size); } static void operator delete[](void *ptr) noexcept { operator delete(ptr); } }; AlignedAllocator: template< typename DataT, size_t AlignmentS = __alignof(DataT) > struct AlignedAllocator { public using value_type = DataT; using pointer = DataT *; using reference = DataT &; using const_pointer = const DataT *; using const_reference = const DataT &; using size_type = size_t; using difference_type = ptrdiff_t; template< typename DataU > struct rebind { public: using other = AlignedAllocator< DataU, AlignmentS >; rebind &operator=(const rebind &r) = delete; rebind &operator=(rebind &&r) = delete; private: rebind() = delete; rebind(const rebind &r) = delete; rebind(rebind &&r) = delete; ~rebind() = delete; }; AlignedAllocator() noexcept = default; AlignedAllocator( const AlignedAllocator< DataT, AlignmentS > &allocator) noexcept = default; AlignedAllocator( AlignedAllocator< DataT, AlignmentS > &&allocator) noexcept = default; template< typename DataU > AlignedAllocator( const AlignedAllocator< DataU, AlignmentS > &allocator) noexcept {} ~AlignedAllocator() = default; AlignedAllocator< DataT, AlignmentS > &operator=( const AlignedAllocator< DataT, AlignmentS > &allocator) noexcept = delete; AlignedAllocator< DataT, AlignmentS > &operator=( AlignedAllocator< DataT, AlignmentS > &&allocator) noexcept = delete; DataT *address(DataT &data) const noexcept { return &data; } const DataT *address(const DataT &data) const noexcept { return &data; } size_t max_size() const noexcept { return (static_cast< size_t >(0) - static_cast< size_t >(1)) / sizeof(DataT); // independent of definition of size_t } DataT *allocate(size_t count) const { return new DataT[count]; } template< typename DataU > DataT *allocate(size_t count, const DataU *) const { return allocate(count); } void deallocate(DataT *data, size_t count) const { if (count == 0) { return; } else if (count == 1) { delete data; } else { delete[] data; } } template< typename DataU, typename... ConstructorArgsT > void construct(DataU *data, ConstructorArgsT&&... args) const { new ((void *)data) DataU(std::forward< ConstructorArgsT >(args)...); // this looks like an allocation after all? } template< typename DataU > void destroy(DataU *data) const { data->~DataU(); } bool operator==( const AlignedAllocator< DataT, AlignmentS > &rhs) const noexcept { return true; // stateless allocator } bool operator!=( const AlignedAllocator< DataT, AlignmentS > &rhs) const noexcept { return false; // stateless allocator } }; I am not sure about the AlignmentS template parameter yet. I think of supporting non-AlignedData values as well. In this case, I would duplicate/replicate the content of my custom operator new/new[]/delete/delete[] in allocate and deallocate themselves.

Viewing all articles
Browse latest Browse all 17825

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>