CoinUtils  trunk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
CoinAlloc.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines