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
00055 #ifndef NVWA_FIXED_MEM_POOL_H
00056 #define NVWA_FIXED_MEM_POOL_H
00057
00058 #include <new>
00059 #include <assert.h>
00060 #include <stdlib.h>
00061 #include "_nvwa.h"
00062 #include "c++11.h"
00063 #include "class_level_lock.h"
00064 #include "mem_pool_base.h"
00065 #include "static_assert.h"
00066
00067 NVWA_NAMESPACE_BEGIN
00068
00072 #ifndef MEM_POOL_ALIGNMENT
00073 #define MEM_POOL_ALIGNMENT sizeof(void*)
00074 #endif
00075
00082 template <class _Tp>
00083 class fixed_mem_pool
00084 {
00085 public:
00086 typedef typename class_level_lock<fixed_mem_pool<_Tp> >::lock lock;
00091 struct alignment
00092 {
00093 static const size_t value = MEM_POOL_ALIGNMENT;
00094 };
00099 struct block_size
00100 {
00101 static const size_t value =
00102 (sizeof(_Tp) + fixed_mem_pool<_Tp>::alignment::value - 1)
00103 & ~(fixed_mem_pool<_Tp>::alignment::value - 1);
00104 };
00105 static void* allocate();
00106 static void deallocate(void*);
00107 static bool initialize(size_t size);
00108 static int deinitialize();
00109 static int get_alloc_count();
00110 static bool is_initialized();
00111 protected:
00112 static bool bad_alloc_handler();
00113 private:
00114 static void* _S_mem_pool_ptr;
00115 static void* _S_first_avail_ptr;
00116 static int _S_alloc_cnt;
00117 };
00118
00120 template <class _Tp>
00121 void* fixed_mem_pool<_Tp>::_S_mem_pool_ptr = NULL;
00122
00124 template <class _Tp>
00125 void* fixed_mem_pool<_Tp>::_S_first_avail_ptr = NULL;
00126
00128 template <class _Tp>
00129 int fixed_mem_pool<_Tp>::_S_alloc_cnt = 0;
00130
00136 template <class _Tp>
00137 inline void* fixed_mem_pool<_Tp>::allocate()
00138 {
00139 lock guard;
00140 for (;;)
00141 {
00142 if (void* result = _S_first_avail_ptr)
00143 {
00144 _S_first_avail_ptr = *(void**)_S_first_avail_ptr;
00145 ++_S_alloc_cnt;
00146 return result;
00147 }
00148 else
00149 if (!bad_alloc_handler())
00150 return NULL;
00151 }
00152 }
00153
00159 template <class _Tp>
00160 inline void fixed_mem_pool<_Tp>::deallocate(void* block_ptr)
00161 {
00162 if (block_ptr == NULL)
00163 return;
00164 lock guard;
00165 assert(_S_alloc_cnt != 0);
00166 --_S_alloc_cnt;
00167 *(void**)block_ptr = _S_first_avail_ptr;
00168 _S_first_avail_ptr = block_ptr;
00169 }
00170
00177 template <class _Tp>
00178 bool fixed_mem_pool<_Tp>::initialize(size_t size)
00179 {
00180 STATIC_ASSERT(alignment::value > 0 && alignment::value <= 8192,
00181 Bad_alignment);
00182 STATIC_ASSERT((alignment::value & (alignment::value - 1)) == 0,
00183 Alignment_must_be_power_of_two);
00184 STATIC_ASSERT(block_size::value >= sizeof(void*),
00185 Alignment_too_small);
00186 assert(!is_initialized());
00187 assert(size > 0);
00188 _S_mem_pool_ptr = mem_pool_base::alloc_sys(size * block_size::value);
00189 _S_first_avail_ptr = _S_mem_pool_ptr;
00190 if (_S_mem_pool_ptr == NULL)
00191 return false;
00192 char* block = (char*)_S_mem_pool_ptr;
00193 while (--size != 0)
00194 {
00195 char* next = block + block_size::value;
00196 *(void**)block = next;
00197 block = next;
00198 }
00199 *(void**)block = NULL;
00200 return true;
00201 }
00202
00210 template <class _Tp>
00211 int fixed_mem_pool<_Tp>::deinitialize()
00212 {
00213 if (_S_alloc_cnt != 0)
00214 return _S_alloc_cnt;
00215 assert(is_initialized());
00216 mem_pool_base::dealloc_sys(_S_mem_pool_ptr);
00217 _S_mem_pool_ptr = NULL;
00218 _S_first_avail_ptr = NULL;
00219 return 0;
00220 }
00221
00227 template <class _Tp>
00228 inline int fixed_mem_pool<_Tp>::get_alloc_count()
00229 {
00230 return _S_alloc_cnt;
00231 }
00232
00238 template <class _Tp>
00239 inline bool fixed_mem_pool<_Tp>::is_initialized()
00240 {
00241 return _S_mem_pool_ptr != NULL;;
00242 }
00243
00252 template <class _Tp>
00253 bool fixed_mem_pool<_Tp>::bad_alloc_handler()
00254 {
00255 return false;
00256 }
00257
00258 NVWA_NAMESPACE_END
00259
00269 #define DECLARE_FIXED_MEM_POOL(_Cls) \
00270 public: \
00271 static void* operator new(size_t size) \
00272 { \
00273 assert(size == sizeof(_Cls)); \
00274 if (void* ptr = NVWA::fixed_mem_pool<_Cls>::allocate()) \
00275 return ptr; \
00276 else \
00277 throw std::bad_alloc(); \
00278 } \
00279 static void operator delete(void* ptr) \
00280 { \
00281 if (ptr != NULL) \
00282 NVWA::fixed_mem_pool<_Cls>::deallocate(ptr); \
00283 }
00284
00290 #define DECLARE_FIXED_MEM_POOL__NOTHROW(_Cls) \
00291 public: \
00292 static void* operator new(size_t size) _NOEXCEPT \
00293 { \
00294 assert(size == sizeof(_Cls)); \
00295 return NVWA::fixed_mem_pool<_Cls>::allocate(); \
00296 } \
00297 static void operator delete(void* ptr) \
00298 { \
00299 if (ptr != NULL) \
00300 NVWA::fixed_mem_pool<_Cls>::deallocate(ptr); \
00301 }
00302
00315 #define DECLARE_FIXED_MEM_POOL__THROW_NOCHECK(_Cls) \
00316 public: \
00317 static void* operator new(size_t size) \
00318 { \
00319 assert(size == sizeof(_Cls)); \
00320 return NVWA::fixed_mem_pool<_Cls>::allocate(); \
00321 } \
00322 static void operator delete(void* ptr) \
00323 { \
00324 if (ptr != NULL) \
00325 NVWA::fixed_mem_pool<_Cls>::deallocate(ptr); \
00326 }
00327
00328 #endif // NVWA_FIXED_MEM_POOL_H