| QxOrm 1.2.5 C++ Object Relational Mapping library

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

static_mem_pool.h
Go to the documentation of this file.

    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 NDEBUG
    00041 #ifndef QT_NO_DEBUG
    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 NDEBUG
    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 // NDEBUG
    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 // QT_NO_DEBUG
    00395 #endif // NDEBUG