aGrUM  0.16.0
fixedAllocator_inl.h
Go to the documentation of this file.
1 
30 // ============================================================================
32 // ============================================================================
33 
34 namespace gum {
35 
36  // ============================================================================
37  // Initializes a Chunk object
38  // ============================================================================
39  INLINE void FixedAllocator::__Chunk::__init(const std::size_t& blockSize,
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.
51  __blocksAvailable = numBlocks;
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  // ============================================================================
65  INLINE void* FixedAllocator::__Chunk::__allocate(const std::size_t& blockSize) {
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.
80  __firstAvailableBlock = *pResult;
81 
82  // We lose one block
84 
85  return pResult;
86  }
87 
88  // ============================================================================
89  // Deallocates a block of memory
90  // ============================================================================
91  INLINE void FixedAllocator::__Chunk::__deallocat(void* pDeallocatedBlock,
92  const std::size_t& blockSize) {
93  // first, ensure that deallocated is in this chunk
94  GUM_ASSERT(pDeallocatedBlock >= __pData);
95 
96  // Conversion pf pointer for handling
97  unsigned char* toRelease = static_cast< unsigned char* >(pDeallocatedBlock);
98 
99  // Alignement check
100  GUM_ASSERT((toRelease - __pData) % blockSize == 0);
101 
102  // First byte of toRelease has now to give the index of current first
103  // available block
104  *toRelease = __firstAvailableBlock;
105 
106  // So that first available block points to it
108  static_cast< unsigned char >((toRelease - __pData) / blockSize);
109 
110  // Truncation check
111  GUM_ASSERT(__firstAvailableBlock == (toRelease - __pData) / blockSize);
112 
113  // We gain one block, yeah
115  }
116 
117  // ============================================================================
118  // Releases the allocated memory
119  // ============================================================================
120  INLINE void FixedAllocator::__Chunk::__release() { delete[] __pData; }
121 
122 
123  // ############################################################################
124  // @name Constructors / Destructors
125  // ############################################################################
126 
127  // ============================================================================
128  // Constructor.
129  // ============================================================================
130  INLINE FixedAllocator::FixedAllocator(const std::size_t& blockSize,
131  const unsigned char& numBlocks) {
132  // GUM_CONSTRUCTOR(FixedAllocator)
133  __blockSize = blockSize;
134  __numBlocks = numBlocks;
135  __allocChunk = __chunks.begin();
136  __deallocChunk = __chunks.begin();
137  }
138 
139  // ============================================================================
140  // Destructor.
141  // ============================================================================
143  for (__Chunks::iterator chunkIter = __chunks.begin();
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  // ============================================================================
157  INLINE void* FixedAllocator::allocate() {
158  if (__chunks.empty() || __allocChunk->__blocksAvailable == 0) {
159  // no available memory in this chunk
160  // Try to find one with memory available
161  for (__Chunks::iterator chunksIter = __chunks.begin();; ++chunksIter) {
162  if (chunksIter == __chunks.end()) {
163  // All chunks are filled up. Adding a new one
164  __chunks.reserve(__chunks.size() + 1);
165  __Chunk newChunk;
166  newChunk.__init(__blockSize, __numBlocks);
167  __chunks.push_back(newChunk);
168  __allocChunk = __chunks.end();
169  --__allocChunk;
171  break;
172  }
173  if (chunksIter->__blocksAvailable > 0) {
174  // Found a chunk
175  __allocChunk = chunksIter;
176  break;
177  }
178  }
179  }
180  return __allocChunk->__allocate(__blockSize);
181  }
182 
183  // ============================================================================
184  // Deallocates a block
185  // ============================================================================
186  INLINE void FixedAllocator::deallocate(void* pDeallocatedBlock) {
187  if (__deallocChunk->__pData > pDeallocatedBlock
188  || pDeallocatedBlock
189  > (__deallocChunk->__pData + (__numBlocks * __blockSize))) {
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()) {
199  if ((__deallocChunk + offset)->__pData <= pDeallocatedBlock
200  && pDeallocatedBlock < ((__deallocChunk + offset)->__pData
201  + (__numBlocks * __blockSize))) {
202  // If pointed chunk contains this pointer, deallocation find the
203  // place
204  __deallocChunk = (__deallocChunk + offset);
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()) {
211  if ((__deallocChunk - offset)->__pData <= pDeallocatedBlock
212  && pDeallocatedBlock < ((__deallocChunk - offset)->__pData
213  + (__numBlocks * __blockSize))) {
214  // If pointed chunk contains this pointer, deallocation find the
215  // place
216  __deallocChunk = (__deallocChunk - offset);
217  break;
218  }
219  }
220  }
221  }
222  __deallocChunk->__deallocat(pDeallocatedBlock, __blockSize);
223  }
224 
225 } // namespace gum
void * allocate()
Allocates a block.
void deallocate(void *pDeallocatedBlock)
Deallocates a block.
unsigned char __blocksAvailable
Number of blocks available in this chunck.
FixedAllocator(const std::size_t &blockSize, const unsigned char &numBlocks=UCHAR_MAX)
Constructor.
__Chunks::iterator __allocChunk
Last Chunk used for an allocation.
Allocates objects of one given size.
void __deallocat(void *p, const std::size_t &blockSize)
Deallocates a block of memory.
std::size_t __blockSize
Size of a memory block allocated.
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
unsigned char __numBlocks
The maximum number of blocks a chunk can allocate.
void * __allocate(const std::size_t &blockSize)
Allocates a block of memory.
unsigned char * __pData
Pointer to the managed memory itself.
__Chunks::iterator __deallocChunk
Last Chunk used for a deallocation.
unsigned char __firstAvailableBlock
Holds the index of the first block available in this chunck.
~FixedAllocator()
Destructor.
void __init(const std::size_t &blockSize, const unsigned char &numBlocks)
Initializes a Chunk object.
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
void __release()
Releases the allocated memory.