QxOrm  1.5.0
C++ Object Relational Mapping library
fixed_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 
00054 #ifndef QT_NO_DEBUG
00055 #ifndef _QX_MODE_RELEASE
00056 #if _QX_USE_MEM_LEAK_DETECTION
00057 
00058 #ifndef _FIXED_MEM_POOL_H
00059 #define _FIXED_MEM_POOL_H
00060 
00061 #ifdef _MSC_VER
00062 #pragma once
00063 #endif
00064 
00065 #include <new>
00066 #include <assert.h>
00067 #include <stdlib.h>
00068 #include "class_level_lock.h"
00069 #include "mem_pool_base.h"
00070 
00074 #ifndef MEM_POOL_ALIGNMENT
00075 #define MEM_POOL_ALIGNMENT 4
00076 #endif
00077 
00078 namespace qx {
00079 namespace memory {
00080 
00087 template <class _Tp>
00088 class fixed_mem_pool
00089 {
00090 public:
00091     typedef typename class_level_lock<fixed_mem_pool<_Tp> >::lock lock;
00092     static void*  allocate();
00093     static void   deallocate(void*);
00094     static bool   initialize(size_t __size);
00095     static int    deinitialize();
00096     static int    get_alloc_count();
00097     static bool   is_initialized();
00098 protected:
00099     static bool   bad_alloc_handler();
00100 private:
00101     static size_t _S_align(size_t __size);
00102     static void*  _S_mem_pool_ptr;
00103     static void*  _S_first_avail_ptr;
00104     static int    _S_alloc_cnt;
00105 };
00106 
00108 template <class _Tp>
00109 void* fixed_mem_pool<_Tp>::_S_mem_pool_ptr = NULL;
00110 
00112 template <class _Tp>
00113 void* fixed_mem_pool<_Tp>::_S_first_avail_ptr = NULL;
00114 
00116 template <class _Tp>
00117 int   fixed_mem_pool<_Tp>::_S_alloc_cnt = 0;
00118 
00124 template <class _Tp>
00125 inline void* fixed_mem_pool<_Tp>::allocate()
00126 {
00127     lock __guard;
00128     for (;;)
00129     {
00130         if (void* __result = _S_first_avail_ptr)
00131         {
00132             _S_first_avail_ptr = *(void**)_S_first_avail_ptr;
00133             ++_S_alloc_cnt;
00134             return __result;
00135         }
00136         else
00137             if (!bad_alloc_handler())
00138                 return NULL;
00139     }
00140 }
00141 
00147 template <class _Tp>
00148 inline void fixed_mem_pool<_Tp>::deallocate(void* __block_ptr)
00149 {
00150     if (__block_ptr == NULL)
00151         return;
00152     lock __guard;
00153     assert(_S_alloc_cnt != 0);
00154     --_S_alloc_cnt;
00155     *(void**)__block_ptr = _S_first_avail_ptr;
00156     _S_first_avail_ptr = __block_ptr;
00157 }
00158 
00165 template <class _Tp>
00166 bool fixed_mem_pool<_Tp>::initialize(size_t __size)
00167 {
00168     size_t __block_size = _S_align(sizeof(_Tp));
00169     assert(!is_initialized());
00170     assert(__size > 0 && __block_size >= sizeof(void*));
00171     _S_mem_pool_ptr = mem_pool_base::alloc_sys(__size * __block_size);
00172     _S_first_avail_ptr = _S_mem_pool_ptr;
00173     if (_S_mem_pool_ptr == NULL)
00174         return false;
00175     char* __block_ = (char*)_S_mem_pool_ptr;
00176     while (--__size != 0)
00177     {
00178         char* __next_ = __block_ + __block_size;
00179         *(void**)__block_ = __next_;
00180         __block_ = __next_;
00181     }
00182     *(void**)__block_ = NULL;
00183     return true;
00184 }
00185 
00193 template <class _Tp>
00194 int fixed_mem_pool<_Tp>::deinitialize()
00195 {
00196     if (_S_alloc_cnt != 0)
00197         return _S_alloc_cnt;
00198     assert(is_initialized());
00199     mem_pool_base::dealloc_sys(_S_mem_pool_ptr);
00200     _S_mem_pool_ptr = NULL;
00201     _S_first_avail_ptr = NULL;
00202     return 0;
00203 }
00204 
00210 template <class _Tp>
00211 inline int fixed_mem_pool<_Tp>::get_alloc_count()
00212 {
00213     return _S_alloc_cnt;
00214 }
00215 
00221 template <class _Tp>
00222 inline bool fixed_mem_pool<_Tp>::is_initialized()
00223 {
00224     return _S_mem_pool_ptr != NULL;;
00225 }
00226 
00235 template <class _Tp>
00236 bool fixed_mem_pool<_Tp>::bad_alloc_handler()
00237 {
00238     return false;
00239 }
00240 
00247 template <class _Tp>
00248 inline size_t fixed_mem_pool<_Tp>::_S_align(size_t __size)
00249 {
00250     return (__size + MEM_POOL_ALIGNMENT - 1)
00251            / MEM_POOL_ALIGNMENT * MEM_POOL_ALIGNMENT;
00252 }
00253 
00254 } // namespace memory
00255 } // namespace qx
00256 
00267 #define DECLARE_FIXED_MEM_POOL(_Cls) \
00268 public: \
00269     static void* operator new(size_t __size) \
00270     { \
00271         assert(__size == sizeof(_Cls)); \
00272         if (void* __ptr = fixed_mem_pool<_Cls>::allocate()) \
00273             return __ptr; \
00274         else \
00275             throw std::bad_alloc(); \
00276     } \
00277     static void  operator delete(void* __ptr) \
00278     { \
00279         if (__ptr != NULL) \
00280             fixed_mem_pool<_Cls>::deallocate(__ptr); \
00281     }
00282 
00289 #define DECLARE_FIXED_MEM_POOL__NOTHROW(_Cls) \
00290 public: \
00291     static void* operator new(size_t __size) throw() \
00292     { \
00293         assert(__size == sizeof(_Cls)); \
00294         return fixed_mem_pool<_Cls>::allocate(); \
00295     } \
00296     static void  operator delete(void* __ptr) \
00297     { \
00298         if (__ptr != NULL) \
00299             fixed_mem_pool<_Cls>::deallocate(__ptr); \
00300     }
00301 
00314 #define DECLARE_FIXED_MEM_POOL__THROW_NOCHECK(_Cls) \
00315 public: \
00316     static void* operator new(size_t __size) \
00317     { \
00318         assert(__size == sizeof(_Cls)); \
00319         return fixed_mem_pool<_Cls>::allocate(); \
00320     } \
00321     static void  operator delete(void* __ptr) \
00322     { \
00323         if (__ptr != NULL) \
00324             fixed_mem_pool<_Cls>::deallocate(__ptr); \
00325     }
00326 
00327 #endif // _FIXED_MEM_POOL_H
00328 #endif // _QX_USE_MEM_LEAK_DETECTION
00329 #endif // _QX_MODE_RELEASE
00330 #endif // QT_NO_DEBUG