CoinUtils
trunk
|
00001 /* $Id$ */ 00002 // Copyright (C) 2007, International Business Machines 00003 // Corporation and others. All Rights Reserved. 00004 // This code is licensed under the terms of the Eclipse Public License (EPL). 00005 00006 #ifndef CoinAlloc_hpp 00007 #define CoinAlloc_hpp 00008 00009 #include "CoinUtilsConfig.h" 00010 #include <cstdlib> 00011 00012 #if !defined(COINUTILS_MEMPOOL_MAXPOOLED) 00013 # define COINUTILS_MEMPOOL_MAXPOOLED -1 00014 #endif 00015 00016 #if (COINUTILS_MEMPOOL_MAXPOOLED >= 0) 00017 00018 #ifndef COINUTILS_MEMPOOL_ALIGNMENT 00019 #define COINUTILS_MEMPOOL_ALIGNMENT 16 00020 #endif 00021 00022 /* Note: 00023 This memory pool implementation assumes that sizeof(size_t) and 00024 sizeof(void*) are both <= COINUTILS_MEMPOOL_ALIGNMENT. 00025 Choosing an alignment of 4 will cause segfault on 64-bit platforms and may 00026 lead to bad performance on 32-bit platforms. So 8 is a mnimum recommended 00027 alignment. Probably 16 does not waste too much space either and may be even 00028 better for performance. One must play with it. 00029 */ 00030 00031 //############################################################################# 00032 00033 #if (COINUTILS_MEMPOOL_ALIGNMENT == 16) 00034 static const std::size_t CoinAllocPtrShift = 4; 00035 static const std::size_t CoinAllocRoundMask = ~((std::size_t)15); 00036 #elif (COINUTILS_MEMPOOL_ALIGNMENT == 8) 00037 static const std::size_t CoinAllocPtrShift = 3; 00038 static const std::size_t CoinAllocRoundMask = ~((std::size_t)7); 00039 #else 00040 #error "COINUTILS_MEMPOOL_ALIGNMENT must be defined as 8 or 16 (or this code needs to be changed :-)" 00041 #endif 00042 00043 //############################################################################# 00044 00045 #ifndef COIN_MEMPOOL_SAVE_BLOCKHEADS 00046 # define COIN_MEMPOOL_SAVE_BLOCKHEADS 0 00047 #endif 00048 00049 //############################################################################# 00050 00051 class CoinMempool 00052 { 00053 private: 00054 #if (COIN_MEMPOOL_SAVE_BLOCKHEADS == 1) 00055 char** block_heads; 00056 std::size_t block_num; 00057 std::size_t max_block_num; 00058 #endif 00059 #if defined(COINUTILS_PTHREADS) && (COINUTILS_PTHREAD == 1) 00060 pthread_mutex_t mutex_; 00061 #endif 00062 int last_block_size_; 00063 char* first_free_; 00064 const std::size_t entry_size_; 00065 00066 private: 00067 CoinMempool(const CoinMempool&); 00068 CoinMempool& operator=(const CoinMempool&); 00069 00070 private: 00071 char* allocate_new_block(); 00072 inline void lock_mutex() { 00073 #if defined(COINUTILS_PTHREADS) && (COINUTILS_PTHREAD == 1) 00074 pthread_mutex_lock(&mutex_); 00075 #endif 00076 } 00077 inline void unlock_mutex() { 00078 #if defined(COINUTILS_PTHREADS) && (COINUTILS_PTHREAD == 1) 00079 pthread_mutex_unlock(&mutex_); 00080 #endif 00081 } 00082 00083 public: 00084 CoinMempool(std::size_t size = 0); 00085 ~CoinMempool(); 00086 00087 char* alloc(); 00088 inline void dealloc(char *p) 00089 { 00090 char** pp = (char**)p; 00091 lock_mutex(); 00092 *pp = first_free_; 00093 first_free_ = p; 00094 unlock_mutex(); 00095 } 00096 }; 00097 00098 //############################################################################# 00099 00112 class CoinAlloc 00113 { 00114 private: 00115 CoinMempool* pool_; 00116 int maxpooled_; 00117 public: 00118 CoinAlloc(); 00119 ~CoinAlloc() {} 00120 00121 inline void* alloc(const std::size_t n) 00122 { 00123 if (maxpooled_ <= 0) { 00124 return std::malloc(n); 00125 } 00126 char *p = NULL; 00127 const std::size_t to_alloc = 00128 ((n+COINUTILS_MEMPOOL_ALIGNMENT-1) & CoinAllocRoundMask) + 00129 COINUTILS_MEMPOOL_ALIGNMENT; 00130 CoinMempool* pool = NULL; 00131 if (maxpooled_ > 0 && to_alloc >= (size_t)maxpooled_) { 00132 p = static_cast<char*>(std::malloc(to_alloc)); 00133 if (p == NULL) throw std::bad_alloc(); 00134 } else { 00135 pool = pool_ + (to_alloc >> CoinAllocPtrShift); 00136 p = pool->alloc(); 00137 } 00138 *((CoinMempool**)p) = pool; 00139 return static_cast<void*>(p+COINUTILS_MEMPOOL_ALIGNMENT); 00140 } 00141 00142 inline void dealloc(void* p) 00143 { 00144 if (maxpooled_ <= 0) { 00145 std::free(p); 00146 return; 00147 } 00148 if (p) { 00149 char* base = static_cast<char*>(p)-COINUTILS_MEMPOOL_ALIGNMENT; 00150 CoinMempool* pool = *((CoinMempool**)base); 00151 if (!pool) { 00152 std::free(base); 00153 } else { 00154 pool->dealloc(base); 00155 } 00156 } 00157 } 00158 }; 00159 00160 extern CoinAlloc CoinAllocator; 00161 00162 //############################################################################# 00163 00164 #if defined(COINUTILS_MEMPOOL_OVERRIDE_NEW) && (COINUTILS_MEMPOOL_OVERRIDE_NEW == 1) 00165 void* operator new(std::size_t size) throw (std::bad_alloc); 00166 void* operator new[](std::size_t) throw (std::bad_alloc); 00167 void operator delete(void*) throw(); 00168 void operator delete[](void*) throw(); 00169 void* operator new(std::size_t, const std::nothrow_t&) throw(); 00170 void* operator new[](std::size_t, const std::nothrow_t&) throw(); 00171 void operator delete(void*, const std::nothrow_t&) throw(); 00172 void operator delete[](void*, const std::nothrow_t&) throw(); 00173 #endif 00174 00175 #endif /*(COINUTILS_MEMPOOL_MAXPOOLED >= 0)*/ 00176 #endif