QxOrm
1.5.0
C++ Object Relational Mapping library
|
00001 // -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- 00002 // vim:tabstop=4:shiftwidth=4:expandtab: 00003 00004 /* 00005 * Copyright (C) 2004-2008 Wu Yongwei <adah at users dot sourceforge dot net> 00006 * 00007 * This software is provided 'as-is', without any express or implied 00008 * warranty. In no event will the authors be held liable for any 00009 * damages arising from the use of this software. 00010 * 00011 * Permission is granted to anyone to use this software for any purpose, 00012 * including commercial applications, and to alter it and redistribute 00013 * it freely, subject to the following restrictions: 00014 * 00015 * 1. The origin of this software must not be misrepresented; you must 00016 * not claim that you wrote the original software. If you use this 00017 * software in a product, an acknowledgement in the product 00018 * documentation would be appreciated but is not required. 00019 * 2. Altered source versions must be plainly marked as such, and must 00020 * not be misrepresented as being the original software. 00021 * 3. This notice may not be removed or altered from any source 00022 * distribution. 00023 * 00024 * This file is part of Stones of Nvwa: 00025 * http://sourceforge.net/projects/nvwa 00026 * 00027 */ 00028 00040 #ifndef QT_NO_DEBUG 00041 #ifndef _QX_MODE_RELEASE 00042 #if _QX_USE_MEM_LEAK_DETECTION 00043 00044 #ifndef _STATIC_MEM_POOL_H 00045 #define _STATIC_MEM_POOL_H 00046 00047 #ifdef _MSC_VER 00048 #pragma once 00049 #endif 00050 00051 #include <new> 00052 #include <stdexcept> 00053 #include <string> 00054 #include <vector> 00055 #include <assert.h> 00056 #include <stddef.h> 00057 #include "class_level_lock.h" 00058 #include "mem_pool_base.h" 00059 00060 /* Defines Work-around for Microsoft Visual C++ 6.0 and Borland C++ 5.5.1 */ 00061 # if (defined(_MSC_VER) && _MSC_VER < 1300) \ 00062 || (defined(__BORLANDC__) && __BORLANDC__ < 0x600) 00063 # define __PRIVATE public 00064 # else 00065 # define __PRIVATE private 00066 # endif 00067 00068 /* Defines the macro for debugging output */ 00069 # ifdef _STATIC_MEM_POOL_DEBUG 00070 # include <iostream> 00071 # define _STATIC_MEM_POOL_TRACE(_Lck, _Msg) \ 00072 { \ 00073 if (_Lck) { \ 00074 static_mem_pool_set::lock __guard; \ 00075 std::cerr << "static_mem_pool: " << _Msg << std::endl; \ 00076 } else { \ 00077 std::cerr << "static_mem_pool: " << _Msg << std::endl; \ 00078 } \ 00079 } 00080 # else 00081 # define _STATIC_MEM_POOL_TRACE(_Lck, _Msg) \ 00082 ((void)0) 00083 # endif 00084 00085 namespace qx { 00086 namespace memory { 00087 00092 class QX_DLL_EXPORT static_mem_pool_set 00093 { 00094 public: 00095 typedef class_level_lock<static_mem_pool_set>::lock lock; 00096 static static_mem_pool_set& instance(); 00097 void recycle(); 00098 void add(mem_pool_base* __memory_pool_p); 00099 00100 __PRIVATE: 00101 ~static_mem_pool_set(); 00102 private: 00103 static_mem_pool_set(); 00104 00105 typedef std::vector<mem_pool_base*> container_type; 00106 container_type _M_memory_pool_set; 00107 00108 /* Forbid their use */ 00109 static_mem_pool_set(const static_mem_pool_set&); 00110 const static_mem_pool_set& operator=(const static_mem_pool_set&); 00111 }; 00112 00123 template <size_t _Sz, int _Gid = -1> 00124 class static_mem_pool : public mem_pool_base 00125 { 00126 typedef typename class_level_lock<static_mem_pool<_Sz, _Gid>, (_Gid < 0)> 00127 ::lock lock; 00128 public: 00137 static static_mem_pool& instance() 00138 { 00139 lock __guard; 00140 if (!_S_instance_p) 00141 { 00142 _S_instance_p = _S_create_instance(); 00143 } 00144 return *_S_instance_p; 00145 } 00153 static static_mem_pool& instance_known() 00154 { 00155 assert(_S_instance_p != NULL); 00156 return *_S_instance_p; 00157 } 00166 void* allocate() 00167 { 00168 { 00169 lock __guard; 00170 if (_S_memory_block_p) 00171 { 00172 void* __result = _S_memory_block_p; 00173 _S_memory_block_p = _S_memory_block_p->_M_next; 00174 return __result; 00175 } 00176 } 00177 return _S_alloc_sys(_S_align(_Sz)); 00178 } 00184 void deallocate(void* __ptr) 00185 { 00186 assert(__ptr != NULL); 00187 lock __guard; 00188 _Block_list* __block_ = reinterpret_cast<_Block_list*>(__ptr); 00189 __block_->_M_next = _S_memory_block_p; 00190 _S_memory_block_p = __block_; 00191 } 00192 virtual void recycle(); 00193 00194 private: 00195 static_mem_pool() 00196 { 00197 _STATIC_MEM_POOL_TRACE(true, "static_mem_pool<" << _Sz << ',' 00198 << _Gid << "> is created"); 00199 } 00200 ~static_mem_pool() 00201 { 00202 #ifndef _QX_MODE_RELEASE 00203 #ifndef QT_NO_DEBUG 00204 // Empty the pool to avoid false memory leakage alarms. This is 00205 // generally not necessary for release binaries. 00206 _Block_list* __block_ = _S_memory_block_p; 00207 while (__block_) 00208 { 00209 _Block_list* __next_ = __block_->_M_next; 00210 dealloc_sys(__block_); 00211 __block_ = __next_; 00212 } 00213 _S_memory_block_p = NULL; 00214 #endif // QT_NO_DEBUG 00215 #endif // _QX_MODE_RELEASE 00216 _S_instance_p = NULL; 00217 _S_destroyed = true; 00218 _STATIC_MEM_POOL_TRACE(false, "static_mem_pool<" << _Sz << ',' 00219 << _Gid << "> is destroyed"); 00220 } 00221 static size_t _S_align(size_t __size) 00222 { 00223 return __size >= sizeof(_Block_list) ? __size : sizeof(_Block_list); 00224 } 00225 static void* _S_alloc_sys(size_t __size); 00226 static static_mem_pool* _S_create_instance(); 00227 00228 static bool _S_destroyed; 00229 static static_mem_pool* _S_instance_p; 00230 static mem_pool_base::_Block_list* _S_memory_block_p; 00231 00232 /* Forbid their use */ 00233 static_mem_pool(const static_mem_pool&); 00234 const static_mem_pool& operator=(const static_mem_pool&); 00235 }; 00236 00237 template <size_t _Sz, int _Gid> bool 00238 static_mem_pool<_Sz, _Gid>::_S_destroyed = false; 00239 template <size_t _Sz, int _Gid> mem_pool_base::_Block_list* 00240 static_mem_pool<_Sz, _Gid>::_S_memory_block_p = NULL; 00241 template <size_t _Sz, int _Gid> static_mem_pool<_Sz, _Gid>* 00242 static_mem_pool<_Sz, _Gid>::_S_instance_p = _S_create_instance(); 00243 00249 template <size_t _Sz, int _Gid> 00250 void static_mem_pool<_Sz, _Gid>::recycle() 00251 { 00252 // Only here the global lock in static_mem_pool_set is obtained 00253 // before the pool-specific lock. However, no race conditions are 00254 // found so far. 00255 lock __guard; 00256 _Block_list* __block_ = _S_memory_block_p; 00257 while (__block_) 00258 { 00259 if (_Block_list* __temp_ = __block_->_M_next) 00260 { 00261 _Block_list* __next_ = __temp_->_M_next; 00262 __block_->_M_next = __next_; 00263 dealloc_sys(__temp_); 00264 __block_ = __next_; 00265 } 00266 else 00267 { 00268 break; 00269 } 00270 } 00271 _STATIC_MEM_POOL_TRACE(false, "static_mem_pool<" << _Sz << ',' 00272 << _Gid << "> is recycled"); 00273 } 00274 00275 template <size_t _Sz, int _Gid> 00276 void* static_mem_pool<_Sz, _Gid>::_S_alloc_sys(size_t __size) 00277 { 00278 static_mem_pool_set::lock __guard; 00279 void* __result = mem_pool_base::alloc_sys(__size); 00280 if (!__result) 00281 { 00282 static_mem_pool_set::instance().recycle(); 00283 __result = mem_pool_base::alloc_sys(__size); 00284 } 00285 return __result; 00286 } 00287 00288 template <size_t _Sz, int _Gid> 00289 static_mem_pool<_Sz, _Gid>* static_mem_pool<_Sz, _Gid>::_S_create_instance() 00290 { 00291 if (_S_destroyed) 00292 throw std::runtime_error("dead reference detected"); 00293 00294 static_mem_pool_set::instance(); // Force its creation 00295 static_mem_pool* __inst_p = new static_mem_pool(); 00296 try 00297 { 00298 static_mem_pool_set::instance().add(__inst_p); 00299 } 00300 catch (...) 00301 { 00302 _STATIC_MEM_POOL_TRACE(true, 00303 "Exception occurs in static_mem_pool_set::add"); 00304 // The strange cast below is to work around a bug in GCC 2.95.3 00305 delete static_cast<mem_pool_base*>(__inst_p); 00306 throw; 00307 } 00308 return __inst_p; 00309 } 00310 00311 } // namespace memory 00312 } // namespace qx 00313 00314 #define DECLARE_STATIC_MEM_POOL(_Cls) \ 00315 public: \ 00316 static void* operator new(size_t __size) \ 00317 { \ 00318 assert(__size == sizeof(_Cls)); \ 00319 void* __ptr; \ 00320 __ptr = static_mem_pool<sizeof(_Cls)>:: \ 00321 instance_known().allocate(); \ 00322 if (__ptr == NULL) \ 00323 throw std::bad_alloc(); \ 00324 return __ptr; \ 00325 } \ 00326 static void operator delete(void* __ptr) \ 00327 { \ 00328 if (__ptr) \ 00329 static_mem_pool<sizeof(_Cls)>:: \ 00330 instance_known().deallocate(__ptr); \ 00331 } 00332 00333 #define DECLARE_STATIC_MEM_POOL__NOTHROW(_Cls) \ 00334 public: \ 00335 static void* operator new(size_t __size) throw() \ 00336 { \ 00337 assert(__size == sizeof(_Cls)); \ 00338 return static_mem_pool<sizeof(_Cls)>:: \ 00339 instance_known().allocate(); \ 00340 } \ 00341 static void operator delete(void* __ptr) \ 00342 { \ 00343 if (__ptr) \ 00344 static_mem_pool<sizeof(_Cls)>:: \ 00345 instance_known().deallocate(__ptr); \ 00346 } 00347 00348 #define DECLARE_STATIC_MEM_POOL_GROUPED(_Cls, _Gid) \ 00349 public: \ 00350 static void* operator new(size_t __size) \ 00351 { \ 00352 assert(__size == sizeof(_Cls)); \ 00353 void* __ptr; \ 00354 __ptr = static_mem_pool<sizeof(_Cls), (_Gid)>:: \ 00355 instance_known().allocate(); \ 00356 if (__ptr == NULL) \ 00357 throw std::bad_alloc(); \ 00358 return __ptr; \ 00359 } \ 00360 static void operator delete(void* __ptr) \ 00361 { \ 00362 if (__ptr) \ 00363 static_mem_pool<sizeof(_Cls), (_Gid)>:: \ 00364 instance_known().deallocate(__ptr); \ 00365 } 00366 00367 #define DECLARE_STATIC_MEM_POOL_GROUPED__NOTHROW(_Cls, _Gid) \ 00368 public: \ 00369 static void* operator new(size_t __size) throw() \ 00370 { \ 00371 assert(__size == sizeof(_Cls)); \ 00372 return static_mem_pool<sizeof(_Cls), (_Gid)>:: \ 00373 instance_known().allocate(); \ 00374 } \ 00375 static void operator delete(void* __ptr) \ 00376 { \ 00377 if (__ptr) \ 00378 static_mem_pool<sizeof(_Cls), (_Gid)>:: \ 00379 instance_known().deallocate(__ptr); \ 00380 } 00381 00382 // OBSOLETE: no longer needed 00383 #define PREPARE_STATIC_MEM_POOL(_Cls) \ 00384 std::cerr << "PREPARE_STATIC_MEM_POOL is obsolete!\n"; 00385 00386 // OBSOLETE: no longer needed 00387 #define PREPARE_STATIC_MEM_POOL_GROUPED(_Cls, _Gid) \ 00388 std::cerr << "PREPARE_STATIC_MEM_POOL_GROUPED is obsolete!\n"; 00389 00390 #undef __PRIVATE 00391 00392 #endif // _STATIC_MEM_POOL_H 00393 #endif // _QX_USE_MEM_LEAK_DETECTION 00394 #endif // _QX_MODE_RELEASE 00395 #endif // QT_NO_DEBUG