Tulip 5.7.1
Large graphs analysis and drawing
Loading...
Searching...
No Matches
memorypool.h
1/*
2 *
3 * This file is part of Tulip (https://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
30static const size_t BUFFOBJ = 20;
31
32namespace 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 contiguous 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 */
63template <typename TYPE>
64class MemoryPool {
65public:
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
83private:
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
130template <typename TYPE>
131typename MemoryPool<TYPE>::MemoryChunkManager MemoryPool<TYPE>::_memoryChunkManager;
132} // namespace tlp
133#endif // MEMORYPOOL_H
134///@endcond