aGrUM
3.2.0
a C++ library for (probabilistic) graphical models
Toggle main menu visibility
fixedAllocator.cpp
Go to the documentation of this file.
1
/****************************************************************************
2
* This file is part of the aGrUM/pyAgrum library. *
3
* *
4
* Copyright (c) 2005-2026 by *
5
* - Pierre-Henri WUILLEMIN(_at_LIP6) *
6
* - Christophe GONZALES(_at_AMU) *
7
* *
8
* The aGrUM/pyAgrum library is free software; you can redistribute it *
9
* and/or modify it under the terms of either : *
10
* *
11
* - the GNU Lesser General Public License as published by *
12
* the Free Software Foundation, either version 3 of the License, *
13
* or (at your option) any later version, *
14
* - the MIT license (MIT), *
15
* - or both in dual license, as here. *
16
* *
17
* (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18
* *
19
* This aGrUM/pyAgrum library is distributed in the hope that it will be *
20
* useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26
* OTHER DEALINGS IN THE SOFTWARE. *
27
* *
28
* See LICENCES for more details. *
29
* *
30
* SPDX-FileCopyrightText: Copyright 2005-2026 *
31
* - Pierre-Henri WUILLEMIN(_at_LIP6) *
32
* - Christophe GONZALES(_at_AMU) *
33
* SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34
* *
35
* Contact : info_at_agrum_dot_org *
36
* homepage : http://agrum.gitlab.io *
37
* gitlab : https://gitlab.com/agrumery/agrum *
38
* *
39
****************************************************************************/
40
41
50
// ============================================================================
51
#include <
agrum/base/core/smallobjectallocator/fixedAllocator.h
>
52
// ============================================================================
53
54
#ifdef GUM_NO_INLINE
55
# include <
agrum/base/core/smallobjectallocator/fixedAllocator_inl.h
>
56
#endif
57
58
namespace
gum
{
59
void
FixedAllocator::_Chunk_::_init_
(
const
std::size_t& blockSize,
60
const
unsigned
char
& numBlocks) {
61
// Chunk memory space allocation. A chunk allocates a memory of blockSize *
62
// numBlocks size.
63
// The chunk will then give us numBlocks distinct blocks of blockSize from
64
// that space.
65
_pData_
=
new
unsigned
char
[blockSize * numBlocks];
66
67
// The first available block of memory is logically at the beginning.
68
_firstAvailableBlock_
= 0;
69
70
// The number of block still available is all the blocks at the beginning.
71
_blocksAvailable_
= numBlocks;
72
73
// For each unallocated block, the first byte contains a number.
74
// That number is the index of the next available block
75
// Since we're at the beginning, next free block is the next one simply.
76
// Following code initiate those number for each block
77
unsigned
char
* p =
_pData_
;
78
for
(
unsigned
char
indexBlock = 0; indexBlock != numBlocks; p += blockSize) {
79
*p = ++indexBlock;
80
}
81
}
82
83
void
*
FixedAllocator::_Chunk_::_allocate_
(
const
std::size_t& blockSize) {
84
if
(!
_blocksAvailable_
) {
85
// If no block is available return nullptr
86
return
nullptr
;
87
}
88
89
// _pData_ points to the beginning of allocated space.
90
// _firstAvailableBlock_ gives us how many block to pass before getting
91
// the good one. We have to multiply by blockSize to get the good memory
92
// emplacement
93
unsigned
char
* pResult =
_pData_
+ (
_firstAvailableBlock_
* blockSize);
94
95
// Remember that the first byte of each block gives us the index of next
96
// available slot.
97
// The new first available block will be at the index indicating in this
98
// block.
99
_firstAvailableBlock_
= *pResult;
100
101
// We lose one block
102
--
_blocksAvailable_
;
103
104
return
pResult;
105
}
106
107
void
FixedAllocator::_Chunk_::_deallocat_
(
void
* pDeallocatedBlock,
const
std::size_t& blockSize) {
108
// first, ensure that deallocated is in this chunk
109
GUM_ASSERT(pDeallocatedBlock >=
_pData_
);
110
111
// Conversion pf pointer for handling
112
unsigned
char
* toRelease =
static_cast<
unsigned
char
*
>
(pDeallocatedBlock);
113
114
// Alignement check
115
GUM_ASSERT((toRelease -
_pData_
) % blockSize == 0);
116
117
// First byte of toRelease has now to give the index of current first
118
// available block
119
*toRelease =
_firstAvailableBlock_
;
120
121
// So that first available block points to it
122
_firstAvailableBlock_
=
static_cast<
unsigned
char
>
((toRelease -
_pData_
) / blockSize);
123
124
// Truncation check
125
GUM_ASSERT(
_firstAvailableBlock_
== (toRelease -
_pData_
) / blockSize);
126
127
// We gain one block, yeah
128
++
_blocksAvailable_
;
129
}
130
131
void
*
FixedAllocator::allocate
() {
132
if
(
_chunks_
.empty() ||
_allocChunk_
->_blocksAvailable_ == 0) {
133
// no available memory in this chunk
134
// Try to find one with memory available
135
for
(_Chunks_::iterator chunksIter =
_chunks_
.begin();; ++chunksIter) {
136
if
(chunksIter ==
_chunks_
.end()) {
137
// All chunks are filled up. Adding a new one
138
_chunks_
.reserve(
_chunks_
.size() + 1);
139
_Chunk_
newChunk;
140
newChunk.
_init_
(
_blockSize_
,
_numBlocks_
);
141
_chunks_
.push_back(newChunk);
142
_allocChunk_
=
_chunks_
.end();
143
--
_allocChunk_
;
144
_deallocChunk_
=
_allocChunk_
;
145
break
;
146
}
147
if
(chunksIter->_blocksAvailable_ > 0) {
148
// Found a chunk
149
_allocChunk_
= chunksIter;
150
break
;
151
}
152
}
153
}
154
return
_allocChunk_
->_allocate_(
_blockSize_
);
155
}
156
157
void
FixedAllocator::deallocate
(
void
* pDeallocatedBlock) {
158
bool
chunk_found =
true
;
159
if
(
_deallocChunk_
->_pData_ > pDeallocatedBlock
160
|| pDeallocatedBlock > (
_deallocChunk_
->_pData_ + (
_numBlocks_
*
_blockSize_
))) {
161
// If not things get ugly
162
// We have to find where the Chunk containing this pointer is
163
std::ptrdiff_t offset = 0;
164
165
// We perform a bidirectional search from _deallocChunk_
166
bool
iter_ok =
true
;
167
while
(iter_ok) {
168
iter_ok =
false
;
169
++offset;
170
// First we look for the one going to the end of the vector
171
if
((
_deallocChunk_
+ offset) <
_chunks_
.end()) {
172
iter_ok =
true
;
173
if
((
_deallocChunk_
+ offset)->_pData_ <= pDeallocatedBlock
174
&& pDeallocatedBlock
175
< ((
_deallocChunk_
+ offset)->_pData_ + (
_numBlocks_
*
_blockSize_
))) {
176
// If pointed chunk contains this pointer, deallocation find the
177
// place
178
_deallocChunk_
= (
_deallocChunk_
+ offset);
179
chunk_found =
true
;
180
break
;
181
}
182
}
183
184
// Then we look for the one going to the beginning of the vector
185
if
((
_deallocChunk_
- offset) >=
_chunks_
.begin()) {
186
iter_ok =
true
;
187
if
((
_deallocChunk_
- offset)->_pData_ <= pDeallocatedBlock
188
&& pDeallocatedBlock
189
< ((
_deallocChunk_
- offset)->_pData_ + (
_numBlocks_
*
_blockSize_
))) {
190
// If pointed chunk contains this pointer, deallocation find the
191
// place
192
_deallocChunk_
= (
_deallocChunk_
- offset);
193
chunk_found =
true
;
194
break
;
195
}
196
}
197
}
198
}
199
200
if
(chunk_found) {
_deallocChunk_
->_deallocat_(pDeallocatedBlock,
_blockSize_
); }
201
}
202
203
}
// namespace gum
gum::FixedAllocator::_chunks_
_Chunks_ _chunks_
Definition
fixedAllocator.h:196
gum::FixedAllocator::_deallocChunk_
_Chunks_::iterator _deallocChunk_
Last Chunk used for a deallocation.
Definition
fixedAllocator.h:206
gum::FixedAllocator::deallocate
void deallocate(void *pDeallocatedBlock)
Deallocates a block.
Definition
fixedAllocator.cpp:157
gum::FixedAllocator::_numBlocks_
unsigned char _numBlocks_
The maximum number of blocks a chunk can allocate.
Definition
fixedAllocator.h:190
gum::FixedAllocator::_blockSize_
std::size_t _blockSize_
Size of a memory block allocated.
Definition
fixedAllocator.h:185
gum::FixedAllocator::_allocChunk_
_Chunks_::iterator _allocChunk_
Last Chunk used for an allocation.
Definition
fixedAllocator.h:201
gum::FixedAllocator::allocate
void * allocate()
Allocates a block.
Definition
fixedAllocator.cpp:131
fixedAllocator.h
Headers of gum::FixedAllocator.
fixedAllocator_inl.h
Inlines of gum::FixedAllocator.
gum
gum is the global namespace for all aGrUM entities
Definition
agrum.h:46
gum::FixedAllocator::_Chunk_
Allocates objects of one given size.
Definition
fixedAllocator.h:98
gum::FixedAllocator::_Chunk_::_firstAvailableBlock_
unsigned char _firstAvailableBlock_
Holds the index of the first block available in this chunck.
Definition
fixedAllocator.h:127
gum::FixedAllocator::_Chunk_::_deallocat_
void _deallocat_(void *p, const std::size_t &blockSize)
Deallocates a block of memory.
Definition
fixedAllocator.cpp:107
gum::FixedAllocator::_Chunk_::_pData_
unsigned char * _pData_
Pointer to the managed memory itself.
Definition
fixedAllocator.h:122
gum::FixedAllocator::_Chunk_::_allocate_
void * _allocate_(const std::size_t &blockSize)
Allocates a block of memory.
Definition
fixedAllocator.cpp:83
gum::FixedAllocator::_Chunk_::_init_
void _init_(const std::size_t &blockSize, const unsigned char &numBlocks)
Initializes a Chunk object.
Definition
fixedAllocator.cpp:59
gum::FixedAllocator::_Chunk_::_blocksAvailable_
unsigned char _blocksAvailable_
Number of blocks available in this chunck.
Definition
fixedAllocator.h:132
aGrUM
3.2.0
© PHW&CG&others - 2022
DoXyGeN 1.18.0