CoinUtils trunk
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 #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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines