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) {
37  }
38 
39  // copy constructor
40 
41  template < typename Val >
42  INLINE RefPtr< Val >::RefPtr(const RefPtr< Val >& from) :
45 
46  if (_refcount_) ++*_refcount_;
47  }
48 
49  // copy constructor for castable pointers
50 
51  template < typename Val >
52  template < typename DownVal >
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_) {
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
90  _val_ = from._val_;
91 
92  if (_refcount_) ++*_refcount_;
93 
94  // now try to dereference the old dumb pointer
96  }
97 
98  return *this;
99  }
100 
101  // copy operator
102 
103  template < typename Val >
105  // avoid self assignment
106  if (_val_ != from) {
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
135  }
136 
137  return *this;
138  }
139 
140  // copy operator for downcastable pointers
141 
142  template < typename Val >
143  template < typename DownVal >
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
152  _val_ = from._val_;
153 
154  if (_refcount_) ++*_refcount_;
155 
156  // now try to dereference the old dumb pointer
158 
159  return *this;
160  }
161 
162  // destructor: it decrements the Val's reference count
163 
164  template < typename 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 >
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
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
257  ptr2._val_ = ptr1._val_;
258  // modify this's content
259  ptr1._val_ = tmp_val;
261  }
262 
263 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643