Tulip  5.2.1
Large graphs analysis and drawing
memorypool.h
1 /*
2  *
3  * This file is part of Tulip (http://tulip.labri.fr)
4  *
5  * Authors: David Auber and the Tulip development Team
6  * from LaBRI, University of Bordeaux
7  *
8  * Tulip is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation, either version 3
11  * of the License, or (at your option) any later version.
12  *
13  * Tulip is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU General Public License for more details.
17  *
18  */
19 ///@cond DOXYGEN_HIDDEN
20 
21 #ifndef MEMORYPOOL_H
22 #define MEMORYPOOL_H
23 #include <vector>
24 #include <iostream>
25 #include <cstdlib>
26 #include <cassert>
27 
28 #include <tulip/ParallelTools.h>
29 
30 static const size_t BUFFOBJ = 20;
31 
32 namespace tlp {
33 /**
34  * @class MemoryPool
35  * \brief That class enables to easily create a memory pool for an a class
36  *
37  * It allocates chunk of BUFFOBJ size of continous memory to allocate
38  * instance of the class. After a delete the memory is not free, and
39  * will be reused at the next new of the class.
40  *
41  * @warning it is not recommended to inherit from an object that inherit of that class
42  *
43  * The following code only calls malloc one time even if NBTRY object are created
44  * in that example, the speedup is about 23, without MemoryPool malloc is called NBTRY times
45  * @code
46  * class A : public MemoryPool<A> {
47  * public:
48  * A(){}
49  * ~A(){}
50  * int data[1000];
51  * };
52  *
53  * size_t NBTRY = 1000 * 1000;
54  * for (size_t j=0; j < NBTRY; ++j) {
55  * A *a = new A();
56  * a->data[100] = j;
57  * r1 += a->data[100];
58  * delete a;
59  * }
60  * @endcode
61  *
62  */
63 template <typename TYPE>
64 class MemoryPool {
65 public:
66  MemoryPool() {}
67 
68 #ifndef NDEBUG
69  inline void *operator new(size_t sizeofObj) {
70 #else
71  inline void *operator new(size_t) {
72 #endif
73  assert(sizeof(TYPE) == sizeofObj); // to prevent inheritance with different size of object
74  TYPE *t;
75  t = _memoryChunkManager.getObject();
76  return t;
77  }
78 
79  inline void operator delete(void *p) {
80  _memoryChunkManager.releaseObject(p);
81  }
82 
83 private:
84  class MemoryChunkManager {
85  public:
86  ~MemoryChunkManager() {
87  for (unsigned int i = 0; i < TLP_MAX_NB_THREADS; ++i) {
88  for (size_t j = 0; j < _allocatedChunks[i].size(); ++j) {
89  free(_allocatedChunks[i][j]);
90  }
91  }
92  }
93 
94  TYPE *getObject() {
95  unsigned int threadId = tlp::ThreadManager::getThreadNumber();
96  TYPE *result = nullptr;
97 
98  if (_freeObject[threadId].empty()) {
99  void *chunk = malloc(BUFFOBJ * sizeof(TYPE));
100  TYPE *p = static_cast<TYPE *>(chunk);
101  _allocatedChunks[threadId].push_back(chunk);
102 
103  for (size_t j = 0; j < BUFFOBJ - 1; ++j) {
104  _freeObject[threadId].push_back(static_cast<void *>(p));
105  p += 1;
106  }
107 
108  result = p;
109  } else {
110  result = static_cast<TYPE *>(_freeObject[threadId].back());
111  _freeObject[threadId].pop_back();
112  }
113 
114  return result;
115  }
116 
117  void releaseObject(void *p) {
118  unsigned int threadId = tlp::ThreadManager::getThreadNumber();
119  _freeObject[threadId].push_back(p);
120  }
121 
122  private:
123  std::vector<void *> _allocatedChunks[TLP_MAX_NB_THREADS];
124  std::vector<void *> _freeObject[TLP_MAX_NB_THREADS];
125  };
126 
127  static MemoryChunkManager _memoryChunkManager;
128 };
129 
130 template <typename TYPE>
131 typename MemoryPool<TYPE>::MemoryChunkManager MemoryPool<TYPE>::_memoryChunkManager;
132 } // namespace tlp
133 #endif // MEMORYPOOL_H
134 ///@endcond
static unsigned int getThreadNumber()