// -*- c++ -*- /****************************************************************************** * arenaalloc.h * * Arena allocator based on the example logic provided by Nicolai Josuttis * and available at http://www.josuttis.com/libbook/examples.html. * This enhanced work is provided under the terms of the MIT license. * *****************************************************************************/ #ifndef _ARENA_ALLOC_H #define _ARENA_ALLOC_H #include #include #if __cplusplus >= 201103L # include # include #endif // Define macro ARENA_ALLOC_DEBUG to enable some tracing of the allocator #include "arenaallocimpl.h" namespace ArenaAlloc { struct _newAllocatorImpl { // these two functions should be supported by a specialized // allocator for shared memory or another source of specialized // memory such as device mapped memory. void* allocate(size_t numBytes) { return new char[numBytes]; } void deallocate(void* ptr) { delete[] ((char*) ptr); } }; template > class Alloc { private: MemblockImpl* m_impl; public: // type definitions typedef T value_type; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; #if __cplusplus >= 201103L // when containers are swapped, (i.e. vector.swap) // swap the allocators also. This was not specified in c++98 // thus users of this code not using c++11 must // exercise caution when using the swap algorithm or // specialized swap member function. Specifically, // don't swap containers not sharing the same // allocator internal implementation in c++98. This is ok // in c++11. typedef std::true_type propagate_on_container_swap; // container moves should move the allocator also. typedef std::true_type propagate_on_container_move_assignment; #endif // rebind allocator to type U template struct rebind { typedef Alloc other; }; // return address of values pointer address(reference value) const { return &value; } const_pointer address(const_reference value) const { return &value; } Alloc(std::size_t defaultSize = 32768, AllocatorImpl allocImpl = AllocatorImpl()) throw() : m_impl(MemblockImpl::create(defaultSize, allocImpl)) { } Alloc(const Alloc& src) throw() : m_impl(src.m_impl) { m_impl->incrementRefCount(); } template Alloc(const Alloc& src) throw() : m_impl(0) { MemblockImpl::assign(src, m_impl); m_impl->incrementRefCount(); } ~Alloc() throw() { m_impl->decrementRefCount(); } // return maximum number of elements that can be allocated size_type max_size() const throw() { return std::numeric_limits::max() / sizeof(T); } void reset() { m_impl->reset(); } // allocate but don't initialize num elements of type T pointer allocate(size_type num, const void* = 0) { return reinterpret_cast(m_impl->allocate(num * sizeof(T))); } // initialize elements of allocated storage p with value value #if __cplusplus >= 201103L // use c++11 style forwarding to construct the object template void construct(P* obj, Args&&... args) { ::new ((void*) obj) P(std::forward(args)...); } template void destroy(P* obj) { obj->~P(); } #else void construct(pointer p, const T& value) { new ((void*) p) T(value); } void destroy(pointer p) { p->~T(); } #endif // deallocate storage p of deleted elements void deallocate(pointer p, size_type num) { m_impl->deallocate(p); } bool equals(const MemblockImpl* impl) const { return impl == m_impl; } bool operator==(const Alloc& t2) const { return m_impl == t2.m_impl; } friend MemblockImpl; template bool operator==(const Alloc& t2) { return t2.equals(m_impl); } template bool operator!=(const Alloc& t2) { return !t2.equals(m_impl); } // These are extension functions not required for an stl allocator size_t getNumAllocations() { return m_impl->getNumAllocations(); } size_t getNumDeallocations() { return m_impl->getNumDeallocations(); } size_t getNumBytesAllocated() { return m_impl->getNumBytesAllocated(); } }; template template void _memblockimpl::assign(const Alloc >& src, _memblockimpl*& dest) { dest = const_cast<_memblockimpl*>(src.m_impl); } } // namespace ArenaAlloc #endif