00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef ChunkList2_h__
00011 #define ChunkList2_h__
00012
00013 #include <vector>
00014
00021 namespace Memory {
00022 using std::size_t;
00023
00024 template<typename TField>
00025 class FixedSizeAllocator {
00026 protected:
00027
00028 struct Chunk;
00029 typedef typename std::vector<Chunk*> vChunk;
00030 typedef typename vChunk::iterator iChunk;
00031 typedef typename Chunk::BLOCK* pBlock;
00032 typedef const typename Chunk::BLOCK* cBlock;
00033
00034 public:
00035 FixedSizeAllocator(const size_t size, const size_t num)
00036 : _blockSize(size), _blockNum(num), _firstFree(NULL) {
00037 _chunks.reserve(64);
00038 }
00039
00040 ~FixedSizeAllocator() { clear(); }
00041
00042 void init(const size_t size, const size_t num) {
00043 clear();
00044 _blockSize = size;
00045 _blockNum = num;
00046 _firstFree = 0;
00047 }
00048
00049 TField* alloc() {
00050 if(_firstFree == NULL)
00051 addChunk();
00052 _ptr = reinterpret_cast<TField*>(_firstFree);
00053 _firstFree = _firstFree->_next;
00054 return new (_ptr) TField();
00055 }
00056
00057 void free(register TField *const ptr) {
00058 if(ptr) {
00059 reinterpret_cast<pBlock>(ptr)->_next = _firstFree;
00060 _firstFree = reinterpret_cast<pBlock>(ptr);
00061 }
00062 }
00063
00064 protected:
00065 FixedSizeAllocator(const FixedSizeAllocator &);
00066
00067 void clear() {
00068 for(register iChunk it(_chunks.begin()); it != _chunks.end(); ++it)
00069 delete *it;
00070 _chunks.clear();
00071 }
00072
00073 void addChunk() {
00074 register Chunk *const _lastChunk = new Chunk(_blockSize, _blockNum);
00075 _chunks.push_back(_lastChunk);
00076 _firstFree = _lastChunk->_storage;
00077 }
00078
00079 size_t _blockSize;
00080 size_t _blockNum;
00081 pBlock _firstFree;
00082 vChunk _chunks;
00083 TField* _ptr;
00084 };
00085
00087 template<typename TField>
00088 struct FixedSizeAllocator<TField>::Chunk {
00089 union BLOCK {
00090 unsigned char _val[sizeof(TField)];
00091 BLOCK* _next;
00092 } *_storage;
00093 size_t _blockSize;
00094 size_t _blockNum;
00095
00096 Chunk(const size_t size, const size_t num)
00097 : _storage(new BLOCK[size * num]), _blockSize(size), _blockNum(num) {
00098 assert(sizeof(BLOCK) == sizeof(TField));
00099 memset(_storage, 0, size * num * sizeof(BLOCK));
00100 reset();
00101 }
00102
00103 ~Chunk() { delete [] _storage; }
00104
00105 void reset() {
00106 register BLOCK* ptr(_storage);
00107 for(register BLOCK *const end(_storage + _blockSize * (_blockNum - 1)); ptr < end; ptr = ptr->_next)
00108 ptr->_next = ptr + _blockSize;
00109 ptr->_next = NULL;
00110 }
00111
00112 bool inside(register const TField *const ptr) const {
00113 register const TField *const begStorage = reinterpret_cast<TField*>(_storage);
00114 return ptr >= begStorage && ptr < begStorage + _blockNum;
00115 }
00116 };
00117 }
00119 #endif // ChunkList2_h__