missing project/build files
[client-tools.git] / src / external / 3rd / library / platform / utils / Base / TemplateBlockAllocator.h
blob2f211797754ba5b18a4c97c7f056cc8f75a4c97e
1 #ifndef BLOCK_ALLOCATOR_H
2 #define BLOCK_ALLOCATOR_H
4 #if defined _MT || defined _REENTRANT
5 # define USE_ALLOCATOR_MUTEX
6 #endif
9 #include <new>
10 #include "Mutex.h"
12 #ifdef EXTERNAL_DISTRO
13 namespace NAMESPACE
16 #endif
17 namespace Base
19 template<int BLOCK_SIZE>
20 class CBlockAllocator
23 private:
24 class Node
26 public:
27 Node * mNext;
28 unsigned mBuffer[(BLOCK_SIZE-1)/sizeof(unsigned)+1];
31 public:
32 CBlockAllocator() :
33 mMemoryBlockCount(0),
34 mNodesAllocated(0),
35 mNodesUsed(0),
36 mUnusedList(0)
38 for (int block=0; block<MAX_BLOCK_COUNT; block++)
39 mMemoryBlock[block] = 0;
40 Allocate();
43 ~CBlockAllocator()
45 for (int block=0; block<MAX_BLOCK_COUNT; block++)
46 delete[] mMemoryBlock[block];
49 void * Allocate()
51 #ifdef USE_ALLOCATOR_MUTEX
52 mMutex.Lock();
53 #endif
54 void * data;
56 Node * node = mUnusedList;
57 mUnusedList = node->mNext;
58 node->mNext = (Node *)1;
60 data = node->mBuffer;
62 mNodesUsed++;
64 #ifdef USE_ALLOCATOR_MUTEX
65 mMutex.Unlock();
66 #endif
68 return data;
71 void Deallocate(void * data)
73 if (!data)
74 return;
76 char * memoryPtr = reinterpret_cast<char *>(data) - sizeof(Node *);
77 Node * node = reinterpret_cast<Node *>(memoryPtr);
79 #ifdef USE_ALLOCATOR_MUTEX
80 mMutex.Lock();
81 #endif
83 node->mNext = mUnusedList;
84 mUnusedList = node;
85 mNodesUsed--;
87 #ifdef USE_ALLOCATOR_MUTEX
88 mMutex.Unlock();
89 #endif
92 template<class T> T * Construct(const T & object)
94 T * objectPtr;
96 #ifdef USE_ALLOCATOR_MUTEX
97 mMutex.Lock();
98 #endif
99 if (sizeof(T) > BLOCK_SIZE || (!mUnusedList && !Allocate()))
101 char * memoryPtr = reinterpret_cast<char *>(new unsigned[(sizeof(Node *)+sizeof(T)-1)/sizeof(unsigned)+1]);
102 objectPtr = reinterpret_cast<T *>(memoryPtr+sizeof(Node *));
104 *reinterpret_cast<unsigned *>(memoryPtr) = 0;
106 else
108 Node * node = mUnusedList;
109 mUnusedList = node->mNext;
110 node->mNext = (Node *)1;
112 objectPtr = reinterpret_cast<T *>(node->mBuffer);
114 mNodesUsed++;
117 new (objectPtr) T(object);
119 #ifdef USE_ALLOCATOR_MUTEX
120 mMutex.Unlock();
121 #endif
122 return objectPtr;
125 template<class T> void Destroy(T * object)
127 if (!object)
128 return;
130 char * memoryPtr = reinterpret_cast<char *>(object) - sizeof(Node *);
131 Node * node = reinterpret_cast<Node *>(memoryPtr);
133 object->~T();
135 #ifdef USE_ALLOCATOR_MUTEX
136 mMutex.Lock();
137 #endif
138 if (node->mNext == 0)
139 delete []memoryPtr;
140 else
142 node->mNext = mUnusedList;
143 mUnusedList = node;
144 mNodesUsed--;
146 #ifdef USE_ALLOCATOR_MUTEX
147 mMutex.Unlock();
148 #endif
151 template<class T> T * FastConstruct(const T & object)
153 T * objectPtr;
155 if (sizeof(T) > BLOCK_SIZE || (!mUnusedList && !Allocate()))
157 char * memoryPtr = reinterpret_cast<char *>(new unsigned[(sizeof(Node *)+sizeof(T)-1)/sizeof(unsigned)+1]);
158 objectPtr = reinterpret_cast<T *>(memoryPtr+sizeof(Node *));
160 *reinterpret_cast<unsigned *>(memoryPtr) = 0;
162 else
164 Node * node = mUnusedList;
165 mUnusedList = node->mNext;
166 node->mNext = (Node *)1;
168 objectPtr = reinterpret_cast<T *>(node->mBuffer);
170 mNodesUsed++;
173 new (objectPtr) T(object);
175 return objectPtr;
178 template<class T> void FastDestroy(T * object)
180 if (!object)
181 return;
183 char * memoryPtr = reinterpret_cast<char *>(object) - sizeof(Node *);
184 Node * node = reinterpret_cast<Node *>(memoryPtr);
186 object->~T();
188 if (node->mNext == 0)
189 delete []memoryPtr;
190 else
192 node->mNext = mUnusedList;
193 mUnusedList = node;
194 mNodesUsed--;
198 bool Allocate()
200 if (mMemoryBlockCount == MAX_BLOCK_COUNT)
201 return false;
203 unsigned count = (mNodesAllocated ? mNodesAllocated : 32);
205 Node* newMemoryBlock = new Node[count];
206 for (unsigned i=0; i<count-1; i++)
207 newMemoryBlock[i].mNext = &newMemoryBlock[i+1];
208 newMemoryBlock[count-1].mNext = mUnusedList;
210 mUnusedList = newMemoryBlock;
211 mMemoryBlock[mMemoryBlockCount++] = newMemoryBlock;
212 mNodesAllocated += count;
214 return true;
217 private:
218 enum { MAX_BLOCK_COUNT = 32 };
220 void * mMemoryBlock[MAX_BLOCK_COUNT];
221 unsigned mMemoryBlockCount;
222 unsigned mNodesAllocated;
223 unsigned mNodesUsed;
224 Node * mUnusedList;
226 #ifdef USE_ALLOCATOR_MUTEX
227 Base::CMutex mMutex;
228 #endif
234 #ifdef EXTERNAL_DISTRO
236 #endif
238 #endif // BLOCK_ALLOCATOR_H