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
00037 #ifndef NVWA_STATIC_MEM_POOL_H
00038 #define NVWA_STATIC_MEM_POOL_H
00039
00040 #include <new>
00041 #include <stdexcept>
00042 #include <string>
00043 #include <vector>
00044 #include <assert.h>
00045 #include <stddef.h>
00046 #include "_nvwa.h"
00047 #include "c++11.h"
00048 #include "class_level_lock.h"
00049 #include "mem_pool_base.h"
00050
00051
00052 # ifdef _STATIC_MEM_POOL_DEBUG
00053 # include <iostream>
00054 # define _STATIC_MEM_POOL_TRACE(_Lck, _Msg) \
00055 { \
00056 if (_Lck) { \
00057 static_mem_pool_set::lock guard; \
00058 std::cerr << "static_mem_pool: " << _Msg << std::endl; \
00059 } else { \
00060 std::cerr << "static_mem_pool: " << _Msg << std::endl; \
00061 } \
00062 }
00063 # else
00064 # define _STATIC_MEM_POOL_TRACE(_Lck, _Msg) \
00065 ((void)0)
00066 # endif
00067
00068 NVWA_NAMESPACE_BEGIN
00069
00074 class static_mem_pool_set
00075 {
00076 public:
00077 typedef class_level_lock<static_mem_pool_set>::lock lock;
00078 static static_mem_pool_set& instance();
00079 void recycle();
00080 void add(mem_pool_base* memory_pool_p);
00081
00082 private:
00083 static_mem_pool_set();
00084 ~static_mem_pool_set();
00085
00086 typedef std::vector<mem_pool_base*> container_type;
00087 container_type _M_memory_pool_set;
00088
00089
00090 static_mem_pool_set(const static_mem_pool_set&);
00091 const static_mem_pool_set& operator=(const static_mem_pool_set&);
00092 };
00093
00104 template <size_t _Sz, int _Gid = -1>
00105 class static_mem_pool : public mem_pool_base
00106 {
00107 typedef typename class_level_lock<static_mem_pool<_Sz, _Gid>, true>
00108 ::lock lock;
00109 public:
00118 static static_mem_pool& instance()
00119 {
00120 lock guard;
00121 if (!_S_instance_p)
00122 {
00123 _S_instance_p = _S_create_instance();
00124 }
00125 return *_S_instance_p;
00126 }
00134 static static_mem_pool& instance_known()
00135 {
00136 assert(_S_instance_p != NULL);
00137 return *_S_instance_p;
00138 }
00147 void* allocate()
00148 {
00149 {
00150 lock guard;
00151 if (_S_memory_block_p)
00152 {
00153 void* result = _S_memory_block_p;
00154 _S_memory_block_p = _S_memory_block_p->_M_next;
00155 return result;
00156 }
00157 }
00158 return _S_alloc_sys(_S_align(_Sz));
00159 }
00165 void deallocate(void* ptr)
00166 {
00167 assert(ptr != NULL);
00168 lock guard;
00169 _Block_list* block = reinterpret_cast<_Block_list*>(ptr);
00170 block->_M_next = _S_memory_block_p;
00171 _S_memory_block_p = block;
00172 }
00173 virtual void recycle();
00174
00175 private:
00176 static_mem_pool()
00177 {
00178 _STATIC_MEM_POOL_TRACE(true, "static_mem_pool<" << _Sz << ','
00179 << _Gid << "> is created");
00180 }
00181 ~static_mem_pool()
00182 {
00183 # ifdef _DEBUG
00184
00185
00186 _Block_list* block = _S_memory_block_p;
00187 while (block)
00188 {
00189 _Block_list* next = block->_M_next;
00190 dealloc_sys(block);
00191 block = next;
00192 }
00193 _S_memory_block_p = NULL;
00194 # endif
00195 _S_instance_p = NULL;
00196 _S_destroyed = true;
00197 _STATIC_MEM_POOL_TRACE(false, "static_mem_pool<" << _Sz << ','
00198 << _Gid << "> is destroyed");
00199 }
00200 static size_t _S_align(size_t size)
00201 {
00202 return size >= sizeof(_Block_list) ? size : sizeof(_Block_list);
00203 }
00204 static void* _S_alloc_sys(size_t size);
00205 static static_mem_pool* _S_create_instance();
00206
00207 static bool _S_destroyed;
00208 static static_mem_pool* _S_instance_p;
00209 static mem_pool_base::_Block_list* _S_memory_block_p;
00210
00211
00212 static_mem_pool(const static_mem_pool&);
00213 const static_mem_pool& operator=(const static_mem_pool&);
00214 };
00215
00216 template <size_t _Sz, int _Gid> bool
00217 static_mem_pool<_Sz, _Gid>::_S_destroyed = false;
00218 template <size_t _Sz, int _Gid> mem_pool_base::_Block_list*
00219 static_mem_pool<_Sz, _Gid>::_S_memory_block_p = NULL;
00220 template <size_t _Sz, int _Gid> static_mem_pool<_Sz, _Gid>*
00221 static_mem_pool<_Sz, _Gid>::_S_instance_p = _S_create_instance();
00222
00228 template <size_t _Sz, int _Gid>
00229 void static_mem_pool<_Sz, _Gid>::recycle()
00230 {
00231
00232
00233
00234 lock guard;
00235 _Block_list* block = _S_memory_block_p;
00236 while (block)
00237 {
00238 if (_Block_list* temp = block->_M_next)
00239 {
00240 _Block_list* next = temp->_M_next;
00241 block->_M_next = next;
00242 dealloc_sys(temp);
00243 block = next;
00244 }
00245 else
00246 {
00247 break;
00248 }
00249 }
00250 _STATIC_MEM_POOL_TRACE(false, "static_mem_pool<" << _Sz << ','
00251 << _Gid << "> is recycled");
00252 }
00253
00254 template <size_t _Sz, int _Gid>
00255 void* static_mem_pool<_Sz, _Gid>::_S_alloc_sys(size_t size)
00256 {
00257 static_mem_pool_set::lock guard;
00258 void* result = mem_pool_base::alloc_sys(size);
00259 if (!result)
00260 {
00261 static_mem_pool_set::instance().recycle();
00262 result = mem_pool_base::alloc_sys(size);
00263 }
00264 return result;
00265 }
00266
00267 template <size_t _Sz, int _Gid>
00268 static_mem_pool<_Sz, _Gid>* static_mem_pool<_Sz, _Gid>::_S_create_instance()
00269 {
00270 if (_S_destroyed)
00271 throw std::runtime_error("dead reference detected");
00272
00273 static_mem_pool_set::instance();
00274 static_mem_pool* inst_p = new static_mem_pool();
00275 try
00276 {
00277 static_mem_pool_set::instance().add(inst_p);
00278 }
00279 catch (...)
00280 {
00281 _STATIC_MEM_POOL_TRACE(true,
00282 "Exception occurs in static_mem_pool_set::add");
00283
00284 delete static_cast<mem_pool_base*>(inst_p);
00285 throw;
00286 }
00287 return inst_p;
00288 }
00289
00290 NVWA_NAMESPACE_END
00291
00301 #define DECLARE_STATIC_MEM_POOL(_Cls) \
00302 public: \
00303 static void* operator new(size_t size) \
00304 { \
00305 assert(size == sizeof(_Cls)); \
00306 void* ptr; \
00307 ptr = NVWA::static_mem_pool<sizeof(_Cls)>:: \
00308 instance_known().allocate(); \
00309 if (ptr == NULL) \
00310 throw std::bad_alloc(); \
00311 return ptr; \
00312 } \
00313 static void operator delete(void* ptr) \
00314 { \
00315 if (ptr) \
00316 NVWA::static_mem_pool<sizeof(_Cls)>:: \
00317 instance_known().deallocate(ptr); \
00318 }
00319
00329 #define DECLARE_STATIC_MEM_POOL__NOTHROW(_Cls) \
00330 public: \
00331 static void* operator new(size_t size) _NOEXCEPT \
00332 { \
00333 assert(size == sizeof(_Cls)); \
00334 return NVWA::static_mem_pool<sizeof(_Cls)>:: \
00335 instance_known().allocate(); \
00336 } \
00337 static void operator delete(void* ptr) \
00338 { \
00339 if (ptr) \
00340 NVWA::static_mem_pool<sizeof(_Cls)>:: \
00341 instance_known().deallocate(ptr); \
00342 }
00343
00354 #define DECLARE_STATIC_MEM_POOL_GROUPED(_Cls, _Gid) \
00355 public: \
00356 static void* operator new(size_t size) \
00357 { \
00358 assert(size == sizeof(_Cls)); \
00359 void* ptr; \
00360 ptr = NVWA::static_mem_pool<sizeof(_Cls), (_Gid)>:: \
00361 instance_known().allocate(); \
00362 if (ptr == NULL) \
00363 throw std::bad_alloc(); \
00364 return ptr; \
00365 } \
00366 static void operator delete(void* ptr) \
00367 { \
00368 if (ptr) \
00369 NVWA::static_mem_pool<sizeof(_Cls), (_Gid)>:: \
00370 instance_known().deallocate(ptr); \
00371 }
00372
00383 #define DECLARE_STATIC_MEM_POOL_GROUPED__NOTHROW(_Cls, _Gid) \
00384 public: \
00385 static void* operator new(size_t size) _NOEXCEPT \
00386 { \
00387 assert(size == sizeof(_Cls)); \
00388 return NVWA::static_mem_pool<sizeof(_Cls), (_Gid)>:: \
00389 instance_known().allocate(); \
00390 } \
00391 static void operator delete(void* ptr) \
00392 { \
00393 if (ptr) \
00394 NVWA::static_mem_pool<sizeof(_Cls), (_Gid)>:: \
00395 instance_known().deallocate(ptr); \
00396 }
00397
00398 #endif // NVWA_STATIC_MEM_POOL_H