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