aGrUM  0.16.0
refPtr_tpl.h
Go to the documentation of this file.
1 
29 #include <agrum/core/refPtr.h>
30 
31 namespace gum {
32 
33  // default constructor
34 
35  template < typename Val >
36  INLINE RefPtr< Val >::RefPtr(Val* v) :
37  __val(v), __refcount(v ? new unsigned int(1U) : 0) {
38  // for debugging purposes
39  GUM_CONSTRUCTOR(RefPtr);
40  }
41 
42  // copy constructor
43 
44  template < typename Val >
45  INLINE RefPtr< Val >::RefPtr(const RefPtr< Val >& from) :
46  __val(from.__val), __refcount(from.__refcount) {
47  // for debugging purposes
48  GUM_CONS_CPY(RefPtr);
49 
50  if (__refcount) ++*__refcount;
51  }
52 
53  // copy constructor for castable pointers
54 
55  template < typename Val >
56  template < typename DownVal >
58  __val(from.__val), __refcount(from.__refcount) {
59  // for debugging purposes
60  GUM_CONS_CPY(RefPtr);
61 
62  if (__refcount) ++*__refcount;
63  }
64 
65  // removes the current content of the smart pointer
66 
67  template < typename Val >
68  INLINE void RefPtr< Val >::__destroy(unsigned int* count, Val* v) {
69  if (count) {
70  if (*count == 1U) {
71  // do not change the order of the deletes (this prevents memory leaks
72  // when
73  // the delete of v fails (note that this should probably never happen))
74  delete count;
75  delete v;
76  } else
77  --*count;
78  }
79  }
80 
81  // copy operator
82 
83  template < typename Val >
85  // avoid self assignment
86  if (__val != from.__val) {
87  // for debugging purposes
88  GUM_OP_CPY(RefPtr);
89 
90  // keep track of the current refcount and dumb pointer
91  unsigned int* old_refcount = __refcount;
92  Val* old_val = __val;
93 
94  // perform the copy
95  __refcount = from.__refcount;
96  __val = from.__val;
97 
98  if (__refcount) ++*__refcount;
99 
100  // now try to dereference the old dumb pointer
101  __destroy(old_refcount, old_val);
102  }
103 
104  return *this;
105  }
106 
107  // copy operator
108 
109  template < typename Val >
111  // avoid self assignment
112  if (__val != from) {
113  // for debugging purposes
114  GUM_OP_CPY(RefPtr);
115 
116  // keep track of the current refcount and dumb pointer
117  unsigned int* old_refcount = __refcount;
118  Val* old_val = __val;
119 
120  // perform the copy
121  try {
122  if (from)
123  __refcount = new unsigned int(1U);
124  else
125  __refcount = 0;
126 
127  __val = from;
128  } catch (std::bad_alloc&) {
129  if (*old_refcount == 1) {
130  __val = from;
131  delete old_val;
132  return *this;
133  }
134 
135  __refcount = 0;
136  __val = 0;
137  throw;
138  }
139 
140  // now try to dereference the old dumb pointer
141  __destroy(old_refcount, old_val);
142  }
143 
144  return *this;
145  }
146 
147  // copy operator for downcastable pointers
148 
149  template < typename Val >
150  template < typename DownVal >
152  // for debugging purposes
153  GUM_OP_CPY(RefPtr);
154  // keep track of the current refcount and dumb pointer
155  unsigned int* old_refcount = __refcount;
156  Val* old_val = __val;
157 
158  // perform the copy
159  __refcount = from.__refcount;
160  __val = from.__val;
161 
162  if (__refcount) ++*__refcount;
163 
164  // now try to dereference the old dumb pointer
165  __destroy(old_refcount, old_val);
166 
167  return *this;
168  }
169 
170  // destructor: it decrements the Val's reference count
171 
172  template < typename Val >
174  // for debugging purposes
175  GUM_DESTRUCTOR(RefPtr);
177  }
178 
179  // checks whether two RefPtr<Val> are smart pointers for the same element
180 
181  template < typename Val >
182  INLINE bool RefPtr< Val >::operator==(const RefPtr< Val >& from) const {
183  return from.__refcount == __refcount;
184  }
185 
186  // checks whether two RefPtr<Val> are smart pointers for differen elements
187 
188  template < typename Val >
189  INLINE bool RefPtr< Val >::operator!=(const RefPtr< Val >& from) const {
190  return from.__refcount != __refcount;
191  }
192 
193  // dereferencing operator
194 
195  template < typename Val >
196  INLINE Val& RefPtr< Val >::operator*() {
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 const Val& RefPtr< Val >::operator*() const {
206  if (!__val) { GUM_ERROR(NullElement, "dereferencing a nullptr pointer"); }
207 
208  return *__val;
209  }
210 
211  // dereferencing operator
212 
213  template < typename Val >
214  INLINE Val* RefPtr< Val >::operator->() const {
215  if (!__val) { GUM_ERROR(NullElement, "dereferencing a nullptr pointer"); }
216 
217  return __val;
218  }
219 
220  // checks whether a RefPtr points toward something
221 
222  template < typename Val >
223  INLINE RefPtr< Val >::operator bool() const {
224  return (__val != 0);
225  }
226 
227  // dereference what was referenced by the smart pointer
228 
229  template < typename Val >
230  INLINE void RefPtr< Val >::clear() {
231  // keep track of the old pointer and reference count
232  unsigned int* old_refcount = __refcount;
233  Val* old_val = __val;
234  // set properly the dumb pointer and its refcount
235  __val = 0;
236  __refcount = 0;
237  // now try to dereference the old dumb pointer
238  __destroy(old_refcount, old_val);
239  }
240 
241  // returns the number of references on the contained pointer
242 
243  template < typename Val >
244  INLINE unsigned int RefPtr< Val >::refCount() const {
245  if (__refcount == 0) return 0;
246 
247  return *__refcount;
248  }
249 
250  // returns the refcount pointer
251 
252  template < typename Val >
253  INLINE unsigned int* RefPtr< Val >::__refCountPtr() const {
254  return __refcount;
255  }
256 
257  // replace the contents of two RefPtr
258 
259  template < typename Val >
260  void swap(RefPtr< Val >& ptr1, RefPtr< Val >& ptr2) {
261  // save from's content
262  Val* tmp_val = ptr2.__val;
263  unsigned int* tmp_refcount = ptr2.__refcount;
264  // modify from's content
265  ptr2.__refcount = ptr1.__refcount;
266  ptr2.__val = ptr1.__val;
267  // modify this's content
268  ptr1.__val = tmp_val;
269  ptr1.__refcount = tmp_refcount;
270  }
271 
272 } /* namespace gum */
RefPtr< Val > & operator=(const RefPtr< Val > &from)
Copy operator.
Definition: refPtr_tpl.h:84
friend class RefPtr
A friend to allow downcastings.
Definition: refPtr.h:331
~RefPtr()
Class destructor.
Definition: refPtr_tpl.h:173
unsigned int * __refCountPtr() const
A function to return the refcount pointer.
Definition: refPtr_tpl.h:253
Val * operator->() const
Dereferencing operator.
Definition: refPtr_tpl.h:214
void __destroy(unsigned int *, Val *)
A function to remove the content of the smart pointer, if any.
Definition: refPtr_tpl.h:68
friend void swap(RefPtr< Val > &, RefPtr< Val > &)
The swap function must access to gum::RefPtr private parts.
Definition: refPtr_tpl.h:260
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
Smart pointersaGrUM&#39;s smart pointers keep track of the number of times the value they point to is ref...
Definition: refPtr.h:117
Val * __val
The dumb pointer encapsulated into the "smart" pointer.
Definition: refPtr.h:338
bool operator!=(const RefPtr< Val > &from) const
Checks whether two RefPtr<Val> are smart pointers for different elements.
Definition: refPtr_tpl.h:189
bool operator==(const RefPtr< Val > &from) const
Checks whether two RefPtr<Val> are smart pointers for the same element.
Definition: refPtr_tpl.h:182
void clear()
Makes the smart pointer point to 0.
Definition: refPtr_tpl.h:230
Val & operator*()
Dereferencing operator.
Definition: refPtr_tpl.h:196
#define GUM_ERROR(type, msg)
Definition: exceptions.h:55
unsigned int refCount() const
Returns the number of smart pointer referencing the contained pointer.
Definition: refPtr_tpl.h:244
unsigned int * __refcount
A reference counter on *val.
Definition: refPtr.h:341