aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
fixedAllocator_inl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /**
23  * @file
24  * @brief Inlines of gum::FixedAllocator
25  *
26  * @author Pierre-Henri WUILLEMIN(@LIP6) and Jean-Christophe MAGNAN and Christophe
27  * GONZALES(@AMU)
28  *
29  */
30 // ============================================================================
31 #include <agrum/tools/core/smallobjectallocator/fixedAllocator.h>
32 // ============================================================================
33 
34 namespace gum {
35 
36  // ============================================================================
37  // Initializes a Chunk object
38  // ============================================================================
40  const unsigned char& numBlocks) {
41  // Chunk memory space allocation. A chunk allocates a memory of blockSize *
42  // numBlocks size.
43  // The chunk will then give us numBlocks distinct blocks of blockSize from
44  // that space.
45  pData__ = new unsigned char[blockSize * numBlocks];
46 
47  // The first available block of memory is logically at the beginning.
49 
50  // The number of block still available is all the blocks at the beginning.
52 
53  // For each unallocated block, the first byte contains a number.
54  // That number is the index of the next available block
55  // Since we're at the beginning, next free block is the next one simply.
56  // Following code initiate those number for each block
57  unsigned char* p = pData__;
58  for (unsigned char indexBlock = 0; indexBlock != numBlocks; p += blockSize)
59  *p = ++indexBlock;
60  }
61 
62  // ============================================================================
63  // Allocates a block of memory
64  // ============================================================================
66  if (!blocksAvailable__)
67  // If no block is available return nullptr
68  return NULL;
69 
70  // pData__ points to the beginning of allocated space.
71  // firstAvailableBlock__ gives us how many block to pass before getting
72  // the good one. We have to multiply by blockSize to get the good memory
73  // emplacement
74  unsigned char* pResult = pData__ + (firstAvailableBlock__ * blockSize);
75 
76  // Remember that the first byte of each block gives us the index of next
77  // available slot.
78  // The new first availble block will be at the index indicating in this
79  // block.
81 
82  // We lose one block
84 
85  return pResult;
86  }
87 
88  // ============================================================================
89  // Deallocates a block of memory
90  // ============================================================================
92  const std::size_t& blockSize) {
93  // first, ensure that deallocated is in this chunk
95 
96  // Conversion pf pointer for handling
97  unsigned char* toRelease = static_cast< unsigned char* >(pDeallocatedBlock);
98 
99  // Alignement check
101 
102  // First byte of toRelease has now to give the index of current first
103  // available block
105 
106  // So that first available block points to it
108  = static_cast< unsigned char >((toRelease - pData__) / blockSize);
109 
110  // Truncation check
112 
113  // We gain one block, yeah
115  }
116 
117  // ============================================================================
118  // Releases the allocated memory
119  // ============================================================================
121 
122 
123  // ############################################################################
124  // @name Constructors / Destructors
125  // ############################################################################
126 
127  // ============================================================================
128  // Constructor.
129  // ============================================================================
131  const unsigned char& numBlocks) {
132  // GUM_CONSTRUCTOR(FixedAllocator)
137  }
138 
139  // ============================================================================
140  // Destructor.
141  // ============================================================================
144  chunkIter != chunks__.end();
145  ++chunkIter)
146  chunkIter->release__();
147  // GUM_DESTRUCTOR(FixedAllocator)
148  }
149 
150  // ############################################################################
151  // @name Allocator / Deallocator
152  // ############################################################################
153 
154  // ============================================================================
155  // Allocates a block
156  // ============================================================================
158  if (chunks__.empty() || allocChunk__->blocksAvailable__ == 0) {
159  // no available memory in this chunk
160  // Try to find one with memory available
162  if (chunksIter == chunks__.end()) {
163  // All chunks are filled up. Adding a new one
164  chunks__.reserve(chunks__.size() + 1);
169  --allocChunk__;
171  break;
172  }
173  if (chunksIter->blocksAvailable__ > 0) {
174  // Found a chunk
176  break;
177  }
178  }
179  }
181  }
182 
183  // ============================================================================
184  // Deallocates a block
185  // ============================================================================
190  // If not things get ugly
191  // We have to find where the Chunk containing this pointer is
192  std::ptrdiff_t offset = 0;
193 
194  // We perform a bidirectionnal search from deallocChunk__
195  while (true) {
196  ++offset;
197  // First we look for the one going to the end of the vector
198  if ((deallocChunk__ + offset) < chunks__.end()) {
201  + (numBlocks__ * blockSize__))) {
202  // If pointed chunk contains this pointer, deallocation find the
203  // place
205  break;
206  }
207  }
208 
209  // Then we look for the one going to the beginning of the vector
210  if ((deallocChunk__ - offset) >= chunks__.begin()) {
213  + (numBlocks__ * blockSize__))) {
214  // If pointed chunk contains this pointer, deallocation find the
215  // place
217  break;
218  }
219  }
220  }
221  }
223  }
224 
225 } // namespace gum
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669