/* * memalignment.h * * Created on: Dec 13, 2013 * Author: gregor */ #ifndef GLTB_MEMALIGNMENT_H_ #define GLTB_MEMALIGNMENT_H_ #include #include #include namespace gltb { template class AlignedAllocator { typedef T value_type; typedef T* pointer; typedef T& reference; typedef const T* const_pointer; typedef const T& const_reference; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; template struct rebind { typedef AlignedAllocator other; }; pointer address(reference x) const noexcept { return std::addressof(x); } const_pointer address(const_reference x) const noexcept { return std::addressof(x); } pointer allocate(size_type n, AlignedAllocator::const_pointer hint = 0) { // compute required size of allocation std::size_t allocationSize = n + alignment + std::max(alignment, sizeof(void *)); char *realBase = reinterpret_cast(std::malloc(allocationSize)); char *alignedBase; // align base address alignedBase = (realBase + alignment) % alignment; // make sure there is room for the base address at the start of the aligned block if(alignedBase - realBase < sizeof(void *)) { alignedBase += alignment; } // store original base address before aligned block starts reinterpret_cast(alignedBase)[-1] = realBase; return reinterpret_cast(alignedBase); } void deallocate (pointer p, size_type n) { // the real base address of the block is a pointer stored before the aligned start address void *realPointer = reinterpret_cast(p) - 1; std::free(realPointer); } size_type max_size() const throw() { // analogous to GCC STL: return std::size_t(-1) / sizeof(T); } template void construct(U* p, Args&&... args) { ::new( (void *) p)(std::forward(args)...); } template void destroy(U* p) { p->~_Tp(); } }; } #endif /* GLTB_MEMALIGNMENT_H_ */