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
// ============================================================================
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__
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
114
++
blocksAvailable__
;
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
// ============================================================================
142
INLINE
FixedAllocator
::~
FixedAllocator
() {
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__
;
170
deallocChunk__
=
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
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669