aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
fixedAllocator_inl.h
Go to the documentation of this file.
1
/**
2
*
3
* Copyright (c) 2005-2021 by 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
// ============================================================================
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.
48
_firstAvailableBlock_
= 0;
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
83
--
_blocksAvailable_
;
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
107
_firstAvailableBlock_
=
static_cast
<
unsigned
char
>((
toRelease
-
_pData_
) /
blockSize
);
108
109
// Truncation check
110
GUM_ASSERT
(
_firstAvailableBlock_
== (
toRelease
-
_pData_
) /
blockSize
);
111
112
// We gain one block, yeah
113
++
_blocksAvailable_
;
114
}
115
116
// ============================================================================
117
// Releases the allocated memory
118
// ============================================================================
119
INLINE
void
FixedAllocator
::
_Chunk_
::
_release_
() {
delete
[]
_pData_
; }
120
121
122
// ############################################################################
123
// @name Constructors / Destructors
124
// ############################################################################
125
126
// ============================================================================
127
// Constructor.
128
// ============================================================================
129
INLINE
FixedAllocator
::
FixedAllocator
(
const
std
::
size_t
&
blockSize
,
130
const
unsigned
char
&
numBlocks
) {
131
// GUM_CONSTRUCTOR(FixedAllocator);
132
_blockSize_
=
blockSize
;
133
_numBlocks_
=
numBlocks
;
134
_allocChunk_
=
_chunks_
.
begin
();
135
_deallocChunk_
=
_chunks_
.
begin
();
136
}
137
138
// ============================================================================
139
// Destructor.
140
// ============================================================================
141
INLINE
FixedAllocator
::~
FixedAllocator
() {
142
for
(
_Chunks_
::
iterator
chunkIter
=
_chunks_
.
begin
();
chunkIter
!=
_chunks_
.
end
(); ++
chunkIter
)
143
chunkIter
->
_release_
();
144
// GUM_DESTRUCTOR(FixedAllocator);
145
}
146
147
// ############################################################################
148
// @name Allocator / Deallocator
149
// ############################################################################
150
151
// ============================================================================
152
// Allocates a block
153
// ============================================================================
154
INLINE
void
*
FixedAllocator
::
allocate
() {
155
if
(
_chunks_
.
empty
() ||
_allocChunk_
->
_blocksAvailable_
== 0) {
156
// no available memory in this chunk
157
// Try to find one with memory available
158
for
(
_Chunks_
::
iterator
chunksIter
=
_chunks_
.
begin
();; ++
chunksIter
) {
159
if
(
chunksIter
==
_chunks_
.
end
()) {
160
// All chunks are filled up. Adding a new one
161
_chunks_
.
reserve
(
_chunks_
.
size
() + 1);
162
_Chunk_
newChunk
;
163
newChunk
.
_init_
(
_blockSize_
,
_numBlocks_
);
164
_chunks_
.
push_back
(
newChunk
);
165
_allocChunk_
=
_chunks_
.
end
();
166
--
_allocChunk_
;
167
_deallocChunk_
=
_allocChunk_
;
168
break
;
169
}
170
if
(
chunksIter
->
_blocksAvailable_
> 0) {
171
// Found a chunk
172
_allocChunk_
=
chunksIter
;
173
break
;
174
}
175
}
176
}
177
return
_allocChunk_
->
_allocate_
(
_blockSize_
);
178
}
179
180
// ============================================================================
181
// Deallocates a block
182
// ============================================================================
183
INLINE
void
FixedAllocator
::
deallocate
(
void
*
pDeallocatedBlock
) {
184
if
(
_deallocChunk_
->
_pData_
>
pDeallocatedBlock
185
||
pDeallocatedBlock
> (
_deallocChunk_
->
_pData_
+ (
_numBlocks_
*
_blockSize_
))) {
186
// If not things get ugly
187
// We have to find where the Chunk containing this pointer is
188
std
::
ptrdiff_t
offset
= 0;
189
190
// We perform a bidirectionnal search from _deallocChunk_
191
while
(
true
) {
192
++
offset
;
193
// First we look for the one going to the end of the vector
194
if
((
_deallocChunk_
+
offset
) <
_chunks_
.
end
()) {
195
if
((
_deallocChunk_
+
offset
)->
_pData_
<=
pDeallocatedBlock
196
&&
pDeallocatedBlock
197
< ((
_deallocChunk_
+
offset
)->
_pData_
+ (
_numBlocks_
*
_blockSize_
))) {
198
// If pointed chunk contains this pointer, deallocation find the
199
// place
200
_deallocChunk_
= (
_deallocChunk_
+
offset
);
201
break
;
202
}
203
}
204
205
// Then we look for the one going to the beginning of the vector
206
if
((
_deallocChunk_
-
offset
) >=
_chunks_
.
begin
()) {
207
if
((
_deallocChunk_
-
offset
)->
_pData_
<=
pDeallocatedBlock
208
&&
pDeallocatedBlock
209
< ((
_deallocChunk_
-
offset
)->
_pData_
+ (
_numBlocks_
*
_blockSize_
))) {
210
// If pointed chunk contains this pointer, deallocation find the
211
// place
212
_deallocChunk_
= (
_deallocChunk_
-
offset
);
213
break
;
214
}
215
}
216
}
217
}
218
_deallocChunk_
->
_deallocat_
(
pDeallocatedBlock
,
_blockSize_
);
219
}
220
221
}
// namespace gum
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643