Tulip  5.1.0
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 #ifdef _OPENMP
28 #include <omp.h>
29 #endif
30 
31 #ifdef _OPENMP
32 #define THREAD_NUMBER omp_get_thread_num()
33 static const size_t MAXNBTHREADS = 128;
34 #else
35 #define THREAD_NUMBER 0
36 static const size_t MAXNBTHREADS = 1;
37 #endif
38 
39 static const size_t BUFFOBJ = 20;
40 
41 namespace tlp {
42 /**
43  * @class MemoryPool
44  * \brief That class enables to easily create a memory pool for an a class
45  *
46  * It allocates chunk of BUFFOBJ size of continous memory to allocate
47  * instance of the class. After a delete the memory is not free, and
48  * will be reused at the next new of the class.
49  *
50  * @warning it is not recommended to inherit from an object that inherit of that class
51  *
52  * The following code only calls malloc one time even if NBTRY object are created
53  * in that example, the speedup is about 23, without MemoryPool malloc is called NBTRY times
54  * @code
55  * class A : public MemoryPool<A> {
56  * public:
57  * A(){}
58  * ~A(){}
59  * int data[1000];
60  * };
61  *
62  * size_t NBTRY = 1000 * 1000;
63  * for (size_t j=0; j < NBTRY; ++j) {
64  * A *a = new A();
65  * a->data[100] = j;
66  * r1 += a->data[100];
67  * delete a;
68  * }
69  * @endcode
70  *
71  */
72 template <typename TYPE >
73 class MemoryPool {
74 public:
75  MemoryPool() {
76  }
77 
78 #ifndef NDEBUG
79  inline void *operator new( size_t sizeofObj) {
80 #else
81  inline void *operator new( size_t ) {
82 #endif
83  assert(sizeof(TYPE) == sizeofObj); //to prevent inheritance with different size of object
84  TYPE * t;
85  t = _memoryChunkManager.getObject(THREAD_NUMBER);
86  return t;
87  }
88 
89  inline void operator delete( void *p ) {
90  _memoryChunkManager.releaseObject(THREAD_NUMBER, p);
91  }
92 private:
93 
94  class MemoryChunkManager {
95  public:
96 
97  ~MemoryChunkManager() {
98  for (unsigned int i = 0 ; i < MAXNBTHREADS ; ++i) {
99  for (size_t j = 0 ; j < _allocatedChunks[i].size() ; ++j) {
100  free(_allocatedChunks[i][j]);
101  }
102  }
103  }
104 
105  TYPE* getObject(size_t threadId) {
106  TYPE *result;
107 
108  if (_freeObject[threadId].empty()) {
109  void *chunk = malloc(BUFFOBJ * sizeof(TYPE));
110  TYPE * p = reinterpret_cast<TYPE *>(chunk);
111  _allocatedChunks[threadId].push_back(chunk);
112 
113  for (size_t j=0; j< BUFFOBJ - 1; ++j) {
114  _freeObject[threadId].push_back(reinterpret_cast<void *>(p));
115  p += 1;
116  }
117 
118  result = p;
119  }
120  else {
121  result = reinterpret_cast<TYPE *>(_freeObject[threadId].back());
122  _freeObject[threadId].pop_back();
123  }
124 
125  return result;
126  }
127 
128  void releaseObject(size_t threadId, void *p) {
129  _freeObject[threadId].push_back(p);
130  }
131 
132  private:
133  std::vector<void * > _allocatedChunks[MAXNBTHREADS];
134  std::vector<void * > _freeObject[MAXNBTHREADS];
135 
136  };
137 
138  static MemoryChunkManager _memoryChunkManager;
139 
140 };
141 
142 template <typename TYPE >
143 typename MemoryPool<TYPE>::MemoryChunkManager MemoryPool<TYPE>::_memoryChunkManager;
144 
145 }
146 #endif // MEMORYPOOL_H
147 ///@endcond