lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
object_pool.h
00001 /*****************************************************/
00002 /* lean Memory                  (c) Tobias Zirr 2011 */
00003 /*****************************************************/
00004 
00005 #ifndef LEAN_MEMORY_OBJECT_POOL
00006 #define LEAN_MEMORY_OBJECT_POOL
00007 
00008 #include "../lean.h"
00009 #include "../tags/noncopyable.h"
00010 #include "chunk_heap.h"
00011 #include "default_heap.h"
00012 
00013 namespace lean
00014 {
00015 namespace memory
00016 {
00017 
00019 template <class Element, size_t ChunkSize, class Heap = default_heap, size_t StaticChunkSize = ChunkSize, size_t Alignment = alignof(Element)>
00020 class object_pool : public lean::noncopyable
00021 {
00022 public:
00024     typedef Element value_type;
00026     typedef Heap heap_type;
00028     typedef typename heap_type::size_type size_type;
00030     static const size_type chunk_size = ChunkSize;
00032     static const size_type alignment = Alignment;
00033 
00034 private:
00035     typedef chunk_heap<0, Heap, StaticChunkSize * sizeof(Element), Alignment> chunk_heap;
00036     chunk_heap m_heap;
00037 
00038 public:
00040     LEAN_INLINE object_pool(size_type chunkSize = ChunkSize)
00041         : m_heap( max(chunkSize * sizeof(Element), sizeof(Element) + (Alignment - 1)) ) { }
00043     LEAN_INLINE ~object_pool()
00044     {
00045         clear();
00046     }
00047 
00049     void clear()
00050     {
00051         char *chunkEnd = m_heap.currentOffset();
00052         char *chunkBegin = m_heap.clearCurrent();
00053 
00054         while (chunkBegin)
00055         {
00056             const size_t chunkSize = (chunkEnd - chunkBegin);
00057 
00058             char *current = align<Alignment>(chunkBegin);
00059 
00060             while (sizeof(Element) + static_cast<size_t>(current - chunkBegin) <= chunkSize)
00061             {
00062                 reinterpret_cast<Element*>(current)->~Element();
00063 
00064                 current = align<Alignment>(current + sizeof(Element));
00065             }
00066 
00067             char *nextChunkBegin = m_heap.clearFreeNext();
00068 
00069             if (nextChunkBegin != chunkBegin)
00070             {
00071                 chunkBegin = nextChunkBegin;
00072                 chunkEnd = chunkBegin
00073                     + ((m_heap.currentStatic()) ? StaticChunkSize * sizeof(Element) : m_heap.nextChunkSize());
00074             }
00075             else
00076                 chunkBegin = nullptr;
00077         }
00078     }
00079 
00081     LEAN_INLINE void* allocate() throw()
00082     {
00083         return m_heap.allocate<Alignment>( sizeof(Element) );
00084     }
00086     LEAN_INLINE Element* place(const Element &value) throw()
00087     {
00088         return new( m_heap.allocate<Alignment>( sizeof(Element) ) ) Element(value);
00089     }
00090 #ifndef LEAN0X_NO_RVALUE_REFERENCES
00091 
00092     LEAN_INLINE Element* place(Element &&value) throw()
00093     {
00094         return new( m_heap.allocate<Alignment>( sizeof(Element) ) ) Element( std::move(value) );
00095     }
00096 #endif
00097 };
00098 
00099 } // namespace
00100 
00101 using memory::object_pool;
00102 
00103 } // namespace
00104 
00105 #endif