aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
refPtr_tpl.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 Implementation of aGrUM's "smart" pointers.
25
*
26
* @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27
*/
28
#
include
<
agrum
/
tools
/
core
/
refPtr
.
h
>
29
30
namespace
gum
{
31
32
// default constructor
33
34
template
<
typename
Val >
35
INLINE RefPtr<
Val
>::
RefPtr
(
Val
*
v
) :
_val_
(
v
),
_refcount_
(
v
?
new
unsigned
int
(1U) : 0) {
36
GUM_CONSTRUCTOR
(
RefPtr
);
37
}
38
39
// copy constructor
40
41
template
<
typename
Val
>
42
INLINE
RefPtr
<
Val
>::
RefPtr
(
const
RefPtr
<
Val
>&
from
) :
43
_val_
(
from
.
_val_
),
_refcount_
(
from
.
_refcount_
) {
44
GUM_CONS_CPY
(
RefPtr
);
45
46
if
(
_refcount_
) ++*
_refcount_
;
47
}
48
49
// copy constructor for castable pointers
50
51
template
<
typename
Val
>
52
template
<
typename
DownVal
>
53
INLINE
RefPtr
<
Val
>::
RefPtr
(
const
RefPtr
<
DownVal
>&
from
) :
54
_val_
(
from
.
_val_
),
_refcount_
(
from
.
_refcount_
) {
55
GUM_CONS_CPY
(
RefPtr
);
56
57
if
(
_refcount_
) ++*
_refcount_
;
58
}
59
60
// removes the current content of the smart pointer
61
62
template
<
typename
Val
>
63
INLINE
void
RefPtr
<
Val
>::
_destroy_
(
unsigned
int
*
count
,
Val
*
v
) {
64
if
(
count
) {
65
if
(*
count
== 1U) {
66
// do not change the order of the deletes (this prevents memory leaks
67
// when
68
// the delete of v fails (note that this should probably never happen))
69
delete
count
;
70
delete
v
;
71
}
else
72
--*
count
;
73
}
74
}
75
76
// copy operator
77
78
template
<
typename
Val
>
79
INLINE
RefPtr
<
Val
>&
RefPtr
<
Val
>::
operator
=(
const
RefPtr
<
Val
>&
from
) {
80
// avoid self assignment
81
if
(
_val_
!=
from
.
_val_
) {
82
GUM_OP_CPY
(
RefPtr
)
83
84
// keep track of the current refcount and dumb pointer
85
unsigned
int
*
old_refcount
=
_refcount_
;
86
Val
*
old_val
=
_val_
;
87
88
// perform the copy
89
_refcount_
=
from
.
_refcount_
;
90
_val_
=
from
.
_val_
;
91
92
if
(
_refcount_
) ++*
_refcount_
;
93
94
// now try to dereference the old dumb pointer
95
_destroy_
(
old_refcount
,
old_val
);
96
}
97
98
return
*
this
;
99
}
100
101
// copy operator
102
103
template
<
typename
Val
>
104
INLINE
RefPtr
<
Val
>&
RefPtr
<
Val
>::
operator
=(
Val
*
from
) {
105
// avoid self assignment
106
if
(
_val_
!=
from
) {
107
GUM_OP_CPY
(
RefPtr
);
108
109
// keep track of the current refcount and dumb pointer
110
unsigned
int
*
old_refcount
=
_refcount_
;
111
Val
*
old_val
=
_val_
;
112
113
// perform the copy
114
try
{
115
if
(
from
)
116
_refcount_
=
new
unsigned
int
(1U);
117
else
118
_refcount_
= 0;
119
120
_val_
=
from
;
121
}
catch
(
std
::
bad_alloc
&) {
122
if
(*
old_refcount
== 1) {
123
_val_
=
from
;
124
delete
old_val
;
125
return
*
this
;
126
}
127
128
_refcount_
= 0;
129
_val_
= 0;
130
throw
;
131
}
132
133
// now try to dereference the old dumb pointer
134
_destroy_
(
old_refcount
,
old_val
);
135
}
136
137
return
*
this
;
138
}
139
140
// copy operator for downcastable pointers
141
142
template
<
typename
Val
>
143
template
<
typename
DownVal
>
144
INLINE
RefPtr
<
Val
>&
RefPtr
<
Val
>::
operator
=(
const
RefPtr
<
DownVal
>&
from
) {
145
GUM_OP_CPY
(
RefPtr
)
146
// keep track of the current refcount and dumb pointer
147
unsigned
int
*
old_refcount
=
_refcount_
;
148
Val
*
old_val
=
_val_
;
149
150
// perform the copy
151
_refcount_
=
from
.
_refcount_
;
152
_val_
=
from
.
_val_
;
153
154
if
(
_refcount_
) ++*
_refcount_
;
155
156
// now try to dereference the old dumb pointer
157
_destroy_
(
old_refcount
,
old_val
);
158
159
return
*
this
;
160
}
161
162
// destructor: it decrements the Val's reference count
163
164
template
<
typename
Val
>
165
INLINE
RefPtr
<
Val
>::~
RefPtr
() {
166
GUM_DESTRUCTOR
(
RefPtr
);
167
_destroy_
(
_refcount_
,
_val_
);
168
}
169
170
// checks whether two RefPtr<Val> are smart pointers for the same element
171
172
template
<
typename
Val
>
173
INLINE
bool
RefPtr
<
Val
>::
operator
==(
const
RefPtr
<
Val
>&
from
)
const
{
174
return
from
.
_refcount_
==
_refcount_
;
175
}
176
177
// checks whether two RefPtr<Val> are smart pointers for differen elements
178
179
template
<
typename
Val
>
180
INLINE
bool
RefPtr
<
Val
>::
operator
!=(
const
RefPtr
<
Val
>&
from
)
const
{
181
return
from
.
_refcount_
!=
_refcount_
;
182
}
183
184
// dereferencing operator
185
186
template
<
typename
Val
>
187
INLINE
Val
&
RefPtr
<
Val
>::
operator
*() {
188
if
(!
_val_
) {
GUM_ERROR
(
NullElement
,
"dereferencing a nullptr pointer"
) }
189
190
return
*
_val_
;
191
}
192
193
// dereferencing operator
194
195
template
<
typename
Val
>
196
INLINE
const
Val
&
RefPtr
<
Val
>::
operator
*()
const
{
197
if
(!
_val_
) {
GUM_ERROR
(
NullElement
,
"dereferencing a nullptr pointer"
) }
198
199
return
*
_val_
;
200
}
201
202
// dereferencing operator
203
204
template
<
typename
Val
>
205
INLINE
Val
*
RefPtr
<
Val
>::
operator
->()
const
{
206
if
(!
_val_
) {
GUM_ERROR
(
NullElement
,
"dereferencing a nullptr pointer"
) }
207
208
return
_val_
;
209
}
210
211
// checks whether a RefPtr points toward something
212
213
template
<
typename
Val
>
214
INLINE
RefPtr
<
Val
>::
operator
bool
()
const
{
215
return
(
_val_
!= 0);
216
}
217
218
// dereference what was referenced by the smart pointer
219
220
template
<
typename
Val
>
221
INLINE
void
RefPtr
<
Val
>::
clear
() {
222
// keep track of the old pointer and reference count
223
unsigned
int
*
old_refcount
=
_refcount_
;
224
Val
*
old_val
=
_val_
;
225
// set properly the dumb pointer and its refcount
226
_val_
= 0;
227
_refcount_
= 0;
228
// now try to dereference the old dumb pointer
229
_destroy_
(
old_refcount
,
old_val
);
230
}
231
232
// returns the number of references on the contained pointer
233
234
template
<
typename
Val
>
235
INLINE
unsigned
int
RefPtr
<
Val
>::
refCount
()
const
{
236
if
(
_refcount_
== 0)
return
0;
237
238
return
*
_refcount_
;
239
}
240
241
// returns the refcount pointer
242
243
template
<
typename
Val
>
244
INLINE
unsigned
int
*
RefPtr
<
Val
>::
_refCountPtr_
()
const
{
245
return
_refcount_
;
246
}
247
248
// replace the contents of two RefPtr
249
250
template
<
typename
Val
>
251
void
swap
(
RefPtr
<
Val
>&
ptr1
,
RefPtr
<
Val
>&
ptr2
) {
252
// save from's content
253
Val
*
tmp_val
=
ptr2
.
_val_
;
254
unsigned
int
*
tmp_refcount
=
ptr2
.
_refcount_
;
255
// modify from's content
256
ptr2
.
_refcount_
=
ptr1
.
_refcount_
;
257
ptr2
.
_val_
=
ptr1
.
_val_
;
258
// modify this's content
259
ptr1
.
_val_
=
tmp_val
;
260
ptr1
.
_refcount_
=
tmp_refcount
;
261
}
262
263
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643