00001
00002
00003
00004
00005 #ifndef CoinAlloc_hpp
00006 #define CoinAlloc_hpp
00007
00008 #include "CoinUtilsConfig.h"
00009 #include <cstdlib>
00010
00011 #if !defined(COINUTILS_MEMPOOL_MAXPOOLED)
00012 # define COINUTILS_MEMPOOL_MAXPOOLED -1
00013 #endif
00014
00015 #if (COINUTILS_MEMPOOL_MAXPOOLED >= 0)
00016
00017 #ifdef HAVE_STDLIB_H
00018 #include <stdlib.h>
00019 #endif
00020
00021 #ifndef COINUTILS_MEMPOOL_ALIGNMENT
00022 #define COINUTILS_MEMPOOL_ALIGNMENT 16
00023 #endif
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #if (COINUTILS_MEMPOOL_ALIGNMENT == 16)
00037 static const std::size_t CoinAllocPtrShift = 4;
00038 static const std::size_t CoinAllocRoundMask = ~((std::size_t)15);
00039 #elif (COINUTILS_MEMPOOL_ALIGNMENT == 8)
00040 static const std::size_t CoinAllocPtrShift = 3;
00041 static const std::size_t CoinAllocRoundMask = ~((std::size_t)7);
00042 #else
00043 #error "COINUTILS_MEMPOOL_ALIGNMENT must be defined as 8 or 16 (or this code needs to be changed :-)"
00044 #endif
00045
00046
00047
00048 #ifndef COIN_MEMPOOL_SAVE_BLOCKHEADS
00049 # define COIN_MEMPOOL_SAVE_BLOCKHEADS 0
00050 #endif
00051
00052
00053
00054 class CoinMempool
00055 {
00056 private:
00057 #if (COIN_MEMPOOL_SAVE_BLOCKHEADS == 1)
00058 char** block_heads;
00059 std::size_t block_num;
00060 std::size_t max_block_num;
00061 #endif
00062 #if defined(COINUTILS_PTHREADS) && (COINUTILS_PTHREAD == 1)
00063 pthread_mutex_t mutex_;
00064 #endif
00065 int last_block_size_;
00066 char* first_free_;
00067 const std::size_t entry_size_;
00068
00069 private:
00070 CoinMempool(const CoinMempool&);
00071 CoinMempool& operator=(const CoinMempool&);
00072
00073 private:
00074 char* allocate_new_block();
00075 inline void lock_mutex() {
00076 #if defined(COINUTILS_PTHREADS) && (COINUTILS_PTHREAD == 1)
00077 pthread_mutex_lock(&mutex_);
00078 #endif
00079 }
00080 inline void unlock_mutex() {
00081 #if defined(COINUTILS_PTHREADS) && (COINUTILS_PTHREAD == 1)
00082 pthread_mutex_unlock(&mutex_);
00083 #endif
00084 }
00085
00086 public:
00087 CoinMempool(std::size_t size = 0);
00088 ~CoinMempool();
00089
00090 char* alloc();
00091 inline void dealloc(char *p)
00092 {
00093 char** pp = (char**)p;
00094 lock_mutex();
00095 *pp = first_free_;
00096 first_free_ = p;
00097 unlock_mutex();
00098 }
00099 };
00100
00101
00102
00115 class CoinAlloc
00116 {
00117 private:
00118 CoinMempool* pool_;
00119 int maxpooled_;
00120 public:
00121 CoinAlloc();
00122 ~CoinAlloc() {}
00123
00124 inline void* alloc(const std::size_t n)
00125 {
00126 if (maxpooled_ <= 0) {
00127 return std::malloc(n);
00128 }
00129 char *p = NULL;
00130 const std::size_t to_alloc =
00131 ((n+COINUTILS_MEMPOOL_ALIGNMENT-1) & CoinAllocRoundMask) +
00132 COINUTILS_MEMPOOL_ALIGNMENT;
00133 CoinMempool* pool = NULL;
00134 if (maxpooled_ > 0 && to_alloc >= (size_t)maxpooled_) {
00135 p = static_cast<char*>(std::malloc(to_alloc));
00136 if (p == NULL) throw std::bad_alloc();
00137 } else {
00138 pool = pool_ + (to_alloc >> CoinAllocPtrShift);
00139 p = pool->alloc();
00140 }
00141 *((CoinMempool**)p) = pool;
00142 return static_cast<void*>(p+COINUTILS_MEMPOOL_ALIGNMENT);
00143 }
00144
00145 inline void dealloc(void* p)
00146 {
00147 if (maxpooled_ <= 0) {
00148 std::free(p);
00149 return;
00150 }
00151 if (p) {
00152 char* base = static_cast<char*>(p)-COINUTILS_MEMPOOL_ALIGNMENT;
00153 CoinMempool* pool = *((CoinMempool**)base);
00154 if (!pool) {
00155 std::free(base);
00156 } else {
00157 pool->dealloc(base);
00158 }
00159 }
00160 }
00161 };
00162
00163 extern CoinAlloc CoinAllocator;
00164
00165
00166
00167 #if defined(COINUTILS_MEMPOOL_OVERRIDE_NEW) && (COINUTILS_MEMPOOL_OVERRIDE_NEW == 1)
00168 void* operator new(std::size_t size) throw (std::bad_alloc);
00169 void* operator new[](std::size_t) throw (std::bad_alloc);
00170 void operator delete(void*) throw();
00171 void operator delete[](void*) throw();
00172 void* operator new(std::size_t, const std::nothrow_t&) throw();
00173 void* operator new[](std::size_t, const std::nothrow_t&) throw();
00174 void operator delete(void*, const std::nothrow_t&) throw();
00175 void operator delete[](void*, const std::nothrow_t&) throw();
00176 #endif
00177
00178 #endif
00179 #endif