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