CoinAlloc.hpp
Go to the documentation of this file.
1 /* $Id: CoinAlloc.hpp 1191 2009-07-25 08:38:12Z forrest $ */
2 // Copyright (C) 2007, International Business Machines
3 // Corporation and others. All Rights Reserved.
4 
5 #ifndef CoinAlloc_hpp
6 #define CoinAlloc_hpp
7 
8 #include "CoinUtilsConfig.h"
9 #include <cstdlib>
10 
11 #if !defined(COINUTILS_MEMPOOL_MAXPOOLED)
12 # define COINUTILS_MEMPOOL_MAXPOOLED -1
13 #endif
14 
15 #if (COINUTILS_MEMPOOL_MAXPOOLED >= 0)
16 
17 #ifdef HAVE_STDLIB_H
18 #include <stdlib.h>
19 #endif
20 
21 #ifndef COINUTILS_MEMPOOL_ALIGNMENT
22 #define COINUTILS_MEMPOOL_ALIGNMENT 16
23 #endif
24 
25 /* Note:
26  This memory pool implementation assumes that sizeof(size_t) and
27  sizeof(void*) are both <= COINUTILS_MEMPOOL_ALIGNMENT.
28  Choosing an alignment of 4 will cause segfault on 64-bit platforms and may
29  lead to bad performance on 32-bit platforms. So 8 is a mnimum recommended
30  alignment. Probably 16 does not waste too much space either and may be even
31  better for performance. One must play with it.
32 */
33 
34 //#############################################################################
35 
36 #if (COINUTILS_MEMPOOL_ALIGNMENT == 16)
37 static const std::size_t CoinAllocPtrShift = 4;
38 static const std::size_t CoinAllocRoundMask = ~((std::size_t)15);
39 #elif (COINUTILS_MEMPOOL_ALIGNMENT == 8)
40 static const std::size_t CoinAllocPtrShift = 3;
41 static const std::size_t CoinAllocRoundMask = ~((std::size_t)7);
42 #else
43 #error "COINUTILS_MEMPOOL_ALIGNMENT must be defined as 8 or 16 (or this code needs to be changed :-)"
44 #endif
45 
46 //#############################################################################
47 
48 #ifndef COIN_MEMPOOL_SAVE_BLOCKHEADS
49 # define COIN_MEMPOOL_SAVE_BLOCKHEADS 0
50 #endif
51 
52 //#############################################################################
53 
54 class CoinMempool
55 {
56 private:
57 #if (COIN_MEMPOOL_SAVE_BLOCKHEADS == 1)
58  char** block_heads;
59  std::size_t block_num;
60  std::size_t max_block_num;
61 #endif
62 #if defined(COINUTILS_PTHREADS) && (COINUTILS_PTHREAD == 1)
63  pthread_mutex_t mutex_;
64 #endif
65  int last_block_size_;
66  char* first_free_;
67  const std::size_t entry_size_;
68 
69 private:
70  CoinMempool(const CoinMempool&);
71  CoinMempool& operator=(const CoinMempool&);
72 
73 private:
74  char* allocate_new_block();
75  inline void lock_mutex() {
76 #if defined(COINUTILS_PTHREADS) && (COINUTILS_PTHREAD == 1)
77  pthread_mutex_lock(&mutex_);
78 #endif
79  }
80  inline void unlock_mutex() {
81 #if defined(COINUTILS_PTHREADS) && (COINUTILS_PTHREAD == 1)
82  pthread_mutex_unlock(&mutex_);
83 #endif
84  }
85 
86 public:
87  CoinMempool(std::size_t size = 0);
88  ~CoinMempool();
89 
90  char* alloc();
91  inline void dealloc(char *p)
92  {
93  char** pp = (char**)p;
94  lock_mutex();
95  *pp = first_free_;
96  first_free_ = p;
97  unlock_mutex();
98  }
99 };
100 
101 //#############################################################################
102 
115 class CoinAlloc
116 {
117 private:
118  CoinMempool* pool_;
119  int maxpooled_;
120 public:
121  CoinAlloc();
122  ~CoinAlloc() {}
123 
124  inline void* alloc(const std::size_t n)
125  {
126  if (maxpooled_ <= 0) {
127  return std::malloc(n);
128  }
129  char *p = NULL;
130  const std::size_t to_alloc =
131  ((n+COINUTILS_MEMPOOL_ALIGNMENT-1) & CoinAllocRoundMask) +
132  COINUTILS_MEMPOOL_ALIGNMENT;
133  CoinMempool* pool = NULL;
134  if (maxpooled_ > 0 && to_alloc >= (size_t)maxpooled_) {
135  p = static_cast<char*>(std::malloc(to_alloc));
136  if (p == NULL) throw std::bad_alloc();
137  } else {
138  pool = pool_ + (to_alloc >> CoinAllocPtrShift);
139  p = pool->alloc();
140  }
141  *((CoinMempool**)p) = pool;
142  return static_cast<void*>(p+COINUTILS_MEMPOOL_ALIGNMENT);
143  }
144 
145  inline void dealloc(void* p)
146  {
147  if (maxpooled_ <= 0) {
148  std::free(p);
149  return;
150  }
151  if (p) {
152  char* base = static_cast<char*>(p)-COINUTILS_MEMPOOL_ALIGNMENT;
153  CoinMempool* pool = *((CoinMempool**)base);
154  if (!pool) {
155  std::free(base);
156  } else {
157  pool->dealloc(base);
158  }
159  }
160  }
161 };
162 
163 extern CoinAlloc CoinAllocator;
164 
165 //#############################################################################
166 
167 #if defined(COINUTILS_MEMPOOL_OVERRIDE_NEW) && (COINUTILS_MEMPOOL_OVERRIDE_NEW == 1)
168 void* operator new(std::size_t size) throw (std::bad_alloc);
169 void* operator new[](std::size_t) throw (std::bad_alloc);
170 void operator delete(void*) throw();
171 void operator delete[](void*) throw();
172 void* operator new(std::size_t, const std::nothrow_t&) throw();
173 void* operator new[](std::size_t, const std::nothrow_t&) throw();
174 void operator delete(void*, const std::nothrow_t&) throw();
175 void operator delete[](void*, const std::nothrow_t&) throw();
176 #endif
177 
178 #endif /*(COINUTILS_MEMPOOL_MAXPOOLED >= 0)*/
179 #endif