coin-Bcp
BCP_mempool.hpp
Go to the documentation of this file.
1 // Copyright (C) 2000, International Business Machines
2 // Corporation and others. All Rights Reserved.
3 #ifndef _BCP_MEMPOOL_H
4 #define _BCP_MEMPOOL_H
5 
6 // #define BCP_MEMPOOL_SAVE_BLOCKHEADS
7 
8 class BCP_MemPool {
9 private:
10  const size_t BLOCK_SIZE;
11  size_t entry_size;
12  void ** first_free;
13 #ifdef BCP_MEMPOOL_SAVE_BLOCKHEADS
14  void *** block_heads;
15  size_t block_num;
16  size_t max_block_num;
17 #endif
18 public:
19  // Create an allocator for objects of size n
20  BCP_MemPool(const size_t n, const size_t bl_size = 1023) :
21  BLOCK_SIZE(bl_size), entry_size(n), first_free(0)
22 #ifdef BCP_MEMPOOL_SAVE_BLOCKHEADS
23  , block_heads(0), block_num(0), max_block_num(0)
24 #endif
25  {}
26 
27  // Allocate enough memory for one object;
28  inline void * alloc(size_t n) {
29  if (n != entry_size)
30  return ::operator new(n);
31  void ** p = first_free;
32  if (p) {
33  first_free = static_cast<void **>(*p);
34  } else {
35  // create the new block and save its head
36  const size_t ptr_in_entry = entry_size/sizeof(void**) +
37  ((entry_size % sizeof(void **)) == 0 ? 0 : 1);
38  const size_t dist = ptr_in_entry * sizeof(void **);
39  void ** block = static_cast<void**>(::operator new(BLOCK_SIZE*dist));
40 #ifdef BCP_MEMPOOL_SAVE_BLOCKHEADS
41  // see if we can record another block head. If not, then resize
42  // block_heads
43  if (max_block_num == block_num) {
44  max_block_num = 1.2 * block_num + 10;
45  const void *** old_block_heads = block_heads;
46  block_heads = static_cast<void ***>(::operator new(max_block_num));
47  for (size_t i = 0; i < block_num; ++i)
48  block_heads[i] = old_block_heads[i];
49  ::operator delete(old_block_heads);
50  }
51  // save the new block
52  block_heads[block_num++] = block;
53 #endif
54  // link the entries in the new block together. skip the zeroth
55  // element, that'll be returned to the caller.
56  for (size_t i = 1; i < BLOCK_SIZE-1; ++i)
57  block[i*ptr_in_entry] =
58  static_cast<void*>(block + ((i+1)*ptr_in_entry));
59  // terminate the linked list with a null pointer
60  block[(BLOCK_SIZE-1)*ptr_in_entry] = 0;
61  p = block;
62  first_free = block + ptr_in_entry;
63  }
64  return static_cast<void*>(p);
65  }
66 
67  // Return to the pool the memory pointed to by p;
68  inline void free(void *p, size_t n) {
69  if (p == 0) return;
70  if (n != entry_size) {
71  ::operator delete(p);
72  return;
73  }
74  void** pp = static_cast<void**>(p);
75  *pp = static_cast<void*>(first_free);
76  first_free = pp;
77  }
78  // Deallocate all memory in the pool
80 #ifdef BCP_MEMPOOL_SAVE_BLOCKHEADS
81  for (size_t i = 0; i < block_num; ++i) {
82  ::operator delete(block_heads[i]);
83  }
84  ::operator delete(block_heads);
85 #endif
86  }
87 };
88 
89 #endif
void free(void *p, size_t n)
Definition: BCP_mempool.hpp:68
void * alloc(size_t n)
Definition: BCP_mempool.hpp:28
BCP_MemPool(const size_t n, const size_t bl_size=1023)
Definition: BCP_mempool.hpp:20
size_t entry_size
Definition: BCP_mempool.hpp:11
void ** first_free
Definition: BCP_mempool.hpp:12
const size_t BLOCK_SIZE
Definition: BCP_mempool.hpp:10