00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00053 #ifndef _FIXED_MEM_POOL_H
00054 #define _FIXED_MEM_POOL_H
00055
00056 #include <new>
00057 #include <assert.h>
00058 #include <stdlib.h>
00059 #include "class_level_lock.h"
00060 #include "mem_pool_base.h"
00061
00065 #ifndef MEM_POOL_ALIGNMENT
00066 #define MEM_POOL_ALIGNMENT 4
00067 #endif
00068
00075 template <class _Tp>
00076 class fixed_mem_pool
00077 {
00078 public:
00079 typedef typename class_level_lock<fixed_mem_pool<_Tp> >::lock lock;
00080 static void* allocate();
00081 static void deallocate(void*);
00082 static bool initialize(size_t __size);
00083 static int deinitialize();
00084 static int get_alloc_count();
00085 static bool is_initialized();
00086 protected:
00087 static bool bad_alloc_handler();
00088 private:
00089 static size_t _S_align(size_t __size);
00090 static void* _S_mem_pool_ptr;
00091 static void* _S_first_avail_ptr;
00092 static int _S_alloc_cnt;
00093 };
00094
00096 template <class _Tp>
00097 void* fixed_mem_pool<_Tp>::_S_mem_pool_ptr = NULL;
00098
00100 template <class _Tp>
00101 void* fixed_mem_pool<_Tp>::_S_first_avail_ptr = NULL;
00102
00104 template <class _Tp>
00105 int fixed_mem_pool<_Tp>::_S_alloc_cnt = 0;
00106
00112 template <class _Tp>
00113 inline void* fixed_mem_pool<_Tp>::allocate()
00114 {
00115 lock __guard;
00116 for (;;)
00117 {
00118 if (void* __result = _S_first_avail_ptr)
00119 {
00120 _S_first_avail_ptr = *(void**)_S_first_avail_ptr;
00121 ++_S_alloc_cnt;
00122 return __result;
00123 }
00124 else
00125 if (!bad_alloc_handler())
00126 return NULL;
00127 }
00128 }
00129
00135 template <class _Tp>
00136 inline void fixed_mem_pool<_Tp>::deallocate(void* __block_ptr)
00137 {
00138 if (__block_ptr == NULL)
00139 return;
00140 lock __guard;
00141 assert(_S_alloc_cnt != 0);
00142 --_S_alloc_cnt;
00143 *(void**)__block_ptr = _S_first_avail_ptr;
00144 _S_first_avail_ptr = __block_ptr;
00145 }
00146
00153 template <class _Tp>
00154 bool fixed_mem_pool<_Tp>::initialize(size_t __size)
00155 {
00156 size_t __block_size = _S_align(sizeof(_Tp));
00157 assert(!is_initialized());
00158 assert(__size > 0 && __block_size >= sizeof(void*));
00159 _S_mem_pool_ptr = mem_pool_base::alloc_sys(__size * __block_size);
00160 _S_first_avail_ptr = _S_mem_pool_ptr;
00161 if (_S_mem_pool_ptr == NULL)
00162 return false;
00163 char* __block = (char*)_S_mem_pool_ptr;
00164 while (--__size != 0)
00165 {
00166 char* __next = __block + __block_size;
00167 *(void**)__block = __next;
00168 __block = __next;
00169 }
00170 *(void**)__block = NULL;
00171 return true;
00172 }
00173
00181 template <class _Tp>
00182 int fixed_mem_pool<_Tp>::deinitialize()
00183 {
00184 if (_S_alloc_cnt != 0)
00185 return _S_alloc_cnt;
00186 assert(is_initialized());
00187 mem_pool_base::dealloc_sys(_S_mem_pool_ptr);
00188 _S_mem_pool_ptr = NULL;
00189 _S_first_avail_ptr = NULL;
00190 return 0;
00191 }
00192
00198 template <class _Tp>
00199 inline int fixed_mem_pool<_Tp>::get_alloc_count()
00200 {
00201 return _S_alloc_cnt;
00202 }
00203
00209 template <class _Tp>
00210 inline bool fixed_mem_pool<_Tp>::is_initialized()
00211 {
00212 return _S_mem_pool_ptr != NULL;;
00213 }
00214
00223 template <class _Tp>
00224 bool fixed_mem_pool<_Tp>::bad_alloc_handler()
00225 {
00226 return false;
00227 }
00228
00235 template <class _Tp>
00236 inline size_t fixed_mem_pool<_Tp>::_S_align(size_t __size)
00237 {
00238 return (__size + MEM_POOL_ALIGNMENT - 1)
00239 / MEM_POOL_ALIGNMENT * MEM_POOL_ALIGNMENT;
00240 }
00241
00252 #define DECLARE_FIXED_MEM_POOL(_Cls) \
00253 public: \
00254 static void* operator new(size_t __size) \
00255 { \
00256 assert(__size == sizeof(_Cls)); \
00257 if (void* __ptr = fixed_mem_pool<_Cls>::allocate()) \
00258 return __ptr; \
00259 else \
00260 throw std::bad_alloc(); \
00261 } \
00262 static void operator delete(void* __ptr) \
00263 { \
00264 if (__ptr != NULL) \
00265 fixed_mem_pool<_Cls>::deallocate(__ptr); \
00266 }
00267
00274 #define DECLARE_FIXED_MEM_POOL__NOTHROW(_Cls) \
00275 public: \
00276 static void* operator new(size_t __size) throw() \
00277 { \
00278 assert(__size == sizeof(_Cls)); \
00279 return fixed_mem_pool<_Cls>::allocate(); \
00280 } \
00281 static void operator delete(void* __ptr) \
00282 { \
00283 if (__ptr != NULL) \
00284 fixed_mem_pool<_Cls>::deallocate(__ptr); \
00285 }
00286
00299 #define DECLARE_FIXED_MEM_POOL__THROW_NOCHECK(_Cls) \
00300 public: \
00301 static void* operator new(size_t __size) \
00302 { \
00303 assert(__size == sizeof(_Cls)); \
00304 return fixed_mem_pool<_Cls>::allocate(); \
00305 } \
00306 static void operator delete(void* __ptr) \
00307 { \
00308 if (__ptr != NULL) \
00309 fixed_mem_pool<_Cls>::deallocate(__ptr); \
00310 }
00311
00312 #endif // _FIXED_MEM_POOL_H