00001
00011 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00012 #pragma once
00013 #endif
00014 #ifndef COMMON_FREELIST_H_
00015 #define COMMON_FREELIST_H_
00016
00017 #include <new>
00018
00019 namespace common
00020 {
00021
00026
00028 template <typename T>
00029 class FreeList
00030 {
00031 private:
00032 struct FreeBlock
00033 {
00034 FreeBlock *Next;
00035 };
00036
00037 char *m_Data;
00038 FreeBlock *m_FreeBlocks;
00039 uint m_Capacity;
00040 uint m_FreeCount;
00041
00042
00043 FreeList(const FreeList &);
00044 FreeList & operator = (const FreeList &);
00045
00046 T * PrvTryNew()
00047 {
00048 if (m_FreeBlocks == NULL)
00049 return NULL;
00050 T *Ptr = (T*)m_FreeBlocks;
00051 m_FreeBlocks = m_FreeBlocks->Next;
00052 m_FreeCount--;
00053 return Ptr;
00054 }
00055
00056 T * PrvNew()
00057 {
00058 T *R = PrvTryNew();
00059 if (R == NULL)
00060 throw std::bad_alloc();
00061 return R;
00062 }
00063
00064 public:
00066 FreeList(uint Capacity) :
00067 m_Capacity(Capacity),
00068 m_FreeCount(Capacity)
00069 {
00070 assert(Capacity > 0);
00071 assert(sizeof(T) >= sizeof(FreeBlock) && "FreeList cannot work with such small elements.");
00072
00073 m_Data = new char[Capacity * sizeof(T)];
00074
00075 char *data_current = m_Data;
00076 FreeBlock *fb_prev = NULL, *fb_current;
00077
00078 for (uint i = 0; i < Capacity; i++)
00079 {
00080 fb_current = (FreeBlock*)(data_current);
00081 fb_current->Next = fb_prev;
00082
00083 fb_prev = fb_current;
00084 data_current += sizeof(T);
00085 }
00086
00087 m_FreeBlocks = fb_prev;
00088 }
00089
00090 ~FreeList()
00091 {
00092
00093 delete [] m_Data;
00094 }
00095
00097
00098 T * TryNew() { T *Ptr = PrvTryNew(); return new (Ptr) T; }
00100
00101 T * New () { T *Ptr = PrvNew (); return new (Ptr) T; }
00102
00104 T * TryNew_ctor() { T *Ptr = PrvTryNew(); return new (Ptr) T(); }
00106 T * New_ctor () { T *Ptr = PrvNew (); return new (Ptr) T(); }
00107
00109 template <typename T1> T * TryNew(const T1 &v1) { T *Ptr = PrvTryNew(); return new (Ptr) T(v1); }
00110 template <typename T1> T * New (const T1 &v1) { T *Ptr = PrvNew (); return new (Ptr) T(v1); }
00111 template <typename T1, typename T2> T * TryNew(const T1 &v1, const T2 &v2) { T *Ptr = PrvTryNew(); return new (Ptr) T(v1, v2); }
00112 template <typename T1, typename T2> T * New (const T1 &v1, const T2 &v2) { T *Ptr = PrvNew (); return new (Ptr) T(v1, v2); }
00113 template <typename T1, typename T2, typename T3> T * TryNew(const T1 &v1, const T2 &v2, const T3 &v3) { T *Ptr = PrvTryNew(); return new (Ptr) T(v1, v2, v3); }
00114 template <typename T1, typename T2, typename T3> T * New (const T1 &v1, const T2 &v2, const T3 &v3) { T *Ptr = PrvNew (); return new (Ptr) T(v1, v2, v3); }
00115 template <typename T1, typename T2, typename T3, typename T4> T * TryNew(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) { T *Ptr = PrvTryNew(); return new (Ptr) T(v1, v2, v3, v4); }
00116 template <typename T1, typename T2, typename T3, typename T4> T * New (const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) { T *Ptr = PrvNew (); return new (Ptr) T(v1, v2, v3, v4); }
00117 template <typename T1, typename T2, typename T3, typename T4, typename T5> T * TryNew(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) { T *Ptr = PrvTryNew(); return new (Ptr) T(v1, v2, v3, v4, v5); }
00118 template <typename T1, typename T2, typename T3, typename T4, typename T5> T * New (const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) { T *Ptr = PrvNew (); return new (Ptr) T(v1, v2, v3, v4, v5); }
00119
00121 void Delete(T *x)
00122 {
00123 x->~T();
00124 FreeBlock *new_fb = (FreeBlock*)x;
00125 new_fb->Next = m_FreeBlocks;
00126 m_FreeBlocks = new_fb;
00127 m_FreeCount++;
00128 }
00129
00131 bool IsEmpty() { return m_FreeCount == m_Capacity; }
00133 bool IsFull() { return m_FreeCount == 0; }
00136 uint GetUsedCount() { return m_Capacity - m_FreeCount; }
00137 uint GetFreeCount() { return m_FreeCount; }
00138 uint GetCapacity() { return m_Capacity; }
00140
00142 uint GetUsedSize() { return GetUsedCount() * sizeof(T); }
00143 uint GetFreeSize() { return GetFreeCount() * sizeof(T); }
00144 uint GetAllSize() { return m_Capacity * sizeof(T); }
00146
00148 bool BelongsTo(void *p) { return (p >= m_Data) && (p < m_Data + m_Capacity*sizeof(T)); }
00149 };
00150
00152 template <typename T>
00153 class DynamicFreeList
00154 {
00155 private:
00156 uint m_BlockCapacity;
00157
00158 std::vector< FreeList<T> * > m_Blocks;
00159
00160
00161 DynamicFreeList(const DynamicFreeList &);
00162 DynamicFreeList & operator = (const DynamicFreeList &);
00163
00164 FreeList<T> * GetListForNew()
00165 {
00166 assert(!m_Blocks.empty());
00167
00168 uint LastIndex = m_Blocks.size()-1;
00169 FreeList<T> *LastList = m_Blocks[LastIndex];
00170 uint LastListFreeCount = LastList->GetFreeCount();
00171
00172 if (LastListFreeCount == 0)
00173 {
00174 LastList = new FreeList<T>(m_BlockCapacity);
00175 m_Blocks.push_back(LastList);
00176 }
00177
00178
00179 else
00180 {
00181
00182 LastListFreeCount--;
00183 uint Index = LastIndex;
00184 if (Index > 0)
00185 {
00186 while (Index > 0 && m_Blocks[Index-1]->GetFreeCount() > LastListFreeCount)
00187 {
00188 m_Blocks[Index] = m_Blocks[Index-1];
00189 Index--;
00190 }
00191 m_Blocks[Index] = LastList;
00192 }
00193 }
00194 return LastList;
00195 }
00196
00197 public:
00199 DynamicFreeList(uint BlockCapacity) :
00200 m_BlockCapacity(BlockCapacity)
00201 {
00202 assert(BlockCapacity > 0);
00203
00204 m_Blocks.push_back(new FreeList<T>(BlockCapacity));
00205 }
00206
00207 ~DynamicFreeList()
00208 {
00209 for (uint i = m_Blocks.size(); i--; )
00210 delete m_Blocks[i];
00211 }
00212
00214
00215 T * TryNew() { FreeList<T> *L = GetListForNew(); return L->TryNew(); }
00217
00218 T * New () { FreeList<T> *L = GetListForNew(); return L->New(); }
00219
00221 T * TryNew_ctor() { FreeList<T> *L = GetListForNew(); return L->TryNew_ctor(); }
00223 T * New_ctor () { FreeList<T> *L = GetListForNew(); return L->New_ctor (); }
00224
00226 template <typename T1> T * TryNew(const T1 &v1) { FreeList<T> *L = GetListForNew(); return L->TryNew(v1); }
00227 template <typename T1> T * New (const T1 &v1) { FreeList<T> *L = GetListForNew(); return L->New (v1); }
00228 template <typename T1, typename T2> T * TryNew(const T1 &v1, const T2 &v2) { FreeList<T> *L = GetListForNew(); return L->TryNew(v1, v2); }
00229 template <typename T1, typename T2> T * New (const T1 &v1, const T2 &v2) { FreeList<T> *L = GetListForNew(); return L->New (v1, v2); }
00230 template <typename T1, typename T2, typename T3> T * TryNew(const T1 &v1, const T2 &v2, const T3 &v3) { FreeList<T> *L = GetListForNew(); return L->TryNew(v1, v2, v3); }
00231 template <typename T1, typename T2, typename T3> T * New (const T1 &v1, const T2 &v2, const T3 &v3) { FreeList<T> *L = GetListForNew(); return L->New (v1, v2, v3); }
00232 template <typename T1, typename T2, typename T3, typename T4> T * TryNew(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) { FreeList<T> *L = GetListForNew(); return L->TryNew(v1, v2, v3, v4); }
00233 template <typename T1, typename T2, typename T3, typename T4> T * New (const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) { FreeList<T> *L = GetListForNew(); return L->New (v1, v2, v3, v4); }
00234 template <typename T1, typename T2, typename T3, typename T4, typename T5> T * TryNew(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) { FreeList<T> *L = GetListForNew(); return L->TryNew(v1, v2, v3, v4, v5); }
00235 template <typename T1, typename T2, typename T3, typename T4, typename T5> T * New (const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) { FreeList<T> *L = GetListForNew(); return L->New (v1, v2, v3, v4, v5); }
00236
00238 void Delete(T *x)
00239 {
00240 for (uint i = 0; i < m_Blocks.size(); i++)
00241 {
00242 if (m_Blocks[i]->BelongsTo(x))
00243 {
00244 FreeList<T> *CurrentBlock = m_Blocks[i];
00245 uint MaxIndex = m_Blocks.size()-1;
00246
00247 CurrentBlock->Delete(x);
00248
00249
00250 uint NewFreeCount = CurrentBlock->GetFreeCount();
00251 if (i < MaxIndex)
00252 {
00253 uint j = i;
00254 while (j < MaxIndex && NewFreeCount > m_Blocks[j+1]->GetFreeCount())
00255 {
00256 m_Blocks[j] = m_Blocks[j+1];
00257 j++;
00258 }
00259 m_Blocks[j] = CurrentBlock;
00260 }
00261
00262
00263 if (m_Blocks.size() > 1 && m_Blocks[MaxIndex]->IsEmpty() && m_Blocks[MaxIndex-1]->GetFreeCount() >= (m_BlockCapacity >> 2))
00264 {
00265 delete m_Blocks[MaxIndex];
00266 m_Blocks.pop_back();
00267 }
00268
00269 return;
00270 }
00271 }
00272 assert(0 && "DynamicFreeList.Delete: Cell doesn't belong to any block from the list.");
00273 }
00274
00276 bool IsEmpty()
00277 {
00278 for (uint i = 0; i < m_Blocks.size(); i++)
00279 if (!m_Blocks[i]->IsEmpty())
00280 return false;
00281 return true;
00282 }
00284 bool IsFull()
00285 {
00286 for (uint i = 0; i < m_Blocks.size(); i++)
00287 if (!m_Blocks[i]->IsFull())
00288 return false;
00289 return true;
00290 }
00291 uint GetBlockCount() { return m_Blocks.size(); }
00294 uint GetBlockCapacity() { return m_BlockCapacity; }
00295 uint GetUsedCount()
00296 {
00297 uint R = 0;
00298 for (uint i = 0; i < m_Blocks.size(); i++)
00299 R += m_Blocks[i]->GetUsedCount();
00300 return R;
00301 }
00302 uint GetFreeCount()
00303 {
00304 uint R = 0;
00305 for (uint i = 0; i < m_Blocks.size(); i++)
00306 R += m_Blocks[i]->GetFreeCount();
00307 return R;
00308 }
00309 uint GetCapacity() { return m_BlockCapacity * m_Blocks.size(); }
00311
00313 uint GetBlockSize() { return GetBlockCapacity() * sizeof(T); }
00314 uint GetUsedSize() { return GetUsedCount() * sizeof(T); }
00315 uint GetFreeSize() { return GetFreeCount() * sizeof(T); }
00316 uint GetAllSize() { return GetCapacity() * sizeof(T); }
00318 };
00319
00321
00322
00323 }
00324
00325 #endif