aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
refPtr.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 Class providing aGrUM's "smart" pointers
25  *
26  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27  *
28  */
29 
30 #ifndef GUM_REFPTR_H
31 #define GUM_REFPTR_H
32 
33 #include <new>
34 
35 #include <agrum/agrum.h>
36 
37 namespace gum {
38 
39 #ifndef DOXYGEN_SHOULD_SKIP_THIS
40 
41  template < typename Val >
42  class RefPtr;
43 
44  template < typename Val >
45  class HashFunc;
46 #endif
47 
48  /* DOXYGEN does not like template functions...
49  *
50  * @brief Swap the contents of two RefPtr.
51  * @tparam Val The type referenced by both gum::RefPtr.
52  * @param ptr1 The smart pointer the content of which we swap with that of
53  * ptr2.
54  * @param ptr2 The smart pointer the content of which we replace with that of
55  * ptr1.
56  */
57  /// @brief Swap the contents of two RefPtr.
58  /// @ingroup refptr_group
59  template < typename Val >
60  void swap(RefPtr< Val >& ptr1, RefPtr< Val >& ptr2);
61 
62  // ===========================================================================
63  // === SMART POINTERS ===
64  // ===========================================================================
65  /**
66  * @class RefPtr
67  * @headerfile refPtr.h <agrum/tools/core/refPtr.h>
68  * @brief Smart pointers
69  * @ingroup basicstruct_group
70  * @ingroup refptr_group
71  *
72  * aGrUM's smart pointers keep track of the number of times the value they
73  * point to is referenced. When all smart pointers on a given value have been
74  * deleted, the value itself is also deleted. Thus, using RefPtr, you do not
75  * have to worry anymore about memory leaks. Note however that smart pointers
76  * impose some constraints on the way you program. Here are some rules of
77  * thumb: when several smart pointers must point to the same value, use only
78  * once the constructor taking in argument *val, and use the copy constructor
79  * or the assignment operator for the other smart pointers, else all the
80  * smart pointers will think they point to different values and thus they
81  * will all try to deallocate the dumb pointer they encapsulate, hence
82  * resulting in segmentation faults. In fact, the correct way to use the *val
83  * constructor is writing things like @code RefPtr ( new myObject ) @endcode
84  * In particular, never deallocate yourself a dumb pointer you have
85  * encapsulated into a smart pointer.
86  *
87  * @par Usage example:
88  * @code
89  * // creation of smart pointer
90  * RefPtr<int> ptr1 (new int (4));
91  *
92  * // copying (and sharing) this pointer into new smart pointers
93  * RefPtr<int> ptr2 = ptr1, ptr3;
94  * ptr3 = ptr1;
95  *
96  * // make ptr2 point toward nothing (this does not deallocate int (4) as it
97  * // is pointed to by ptr1 and ptr3)
98  * ptr2.clear ();
99  *
100  * // modifying the value pointed to by the dumb pointer contained in ptr1
101  * *ptr1 = 5;
102  *
103  * // print the content of ptr3
104  * cerr << *ptr3 << " = 5" << endl;
105  *
106  * // check whether ptr1 and ptr3 reference the same dumb pointer
107  * if (ptr1 == ptr2) cerr << "reference the same dumb pointer" << endl;
108  *
109  * // check whether ptr1 and ptr2 contain a dumb pointer
110  * if (ptr1 && !ptr2) cerr << "check containers" << endl;
111  * @endcode
112  *
113  * @tparam Val The type referenced by the gum::RefPtr.
114  */
115  template < typename Val >
116  class RefPtr {
117  public:
118  /// The swap function must access to gum::RefPtr private parts.
119  friend void swap<>(RefPtr< Val >&, RefPtr< Val >&);
120 
121  // ============================================================================
122  /// @name Constructors / Destructors
123  // ============================================================================
124  /// @{
125 
126  /**
127  * @brief Default constructor.
128  *
129  * This constructor creates an object encapsulating the pointer passed in
130  * argument. No copy of the value pointed to by the pointer is performed.
131  * The RefPtr assumes that the value pointed to has been allocated on the
132  * heap using the new operator. If this is not the case, then using RefPtr
133  * will result in an undefined behavior when the RefPtr is destroyed (ok,
134  * we all know what it means: a segmentation fault). To avoid deleting
135  * several times the pointer encapsulated, the safe way to use the RefPtr
136  * is certainly through calls like: @code RefPtr( new myObject ) @endcode
137  * Passing an already allocated pointer to the constructor is not
138  * forbidden. However, in this case, care should be taken not to allow
139  * external functions to delete the value pointed to by val. Moreover, care
140  * should be taken not to allow creating multiple RefPtr using this
141  * constructor on the same val. This would lead to unexpected results
142  * after deletion of the first RefPtr.
143  *
144  * @param val The dumb pointer encapsulated into the object (make sure it
145  * is allocated on the heap)
146  * @throws std::bad_alloc Raised if the complete RefPtr structure cannot be
147  * set properly.
148  */
149  explicit RefPtr(Val* val = 0);
150 
151  /**
152  * @brief Copy constructor.
153  * @param from the smart pointer we wish to make a copy.
154  */
155  RefPtr(const RefPtr< Val >& from);
156 
157  /**
158  * @brief Copy constructor for downcastable pointers.
159  * @param from the smart pointer we wish to make a copy.
160  * @tparam DownVal The downcastable type.
161  */
162  template < typename DownVal >
163  RefPtr(const RefPtr< DownVal >& from);
164 
165  /**
166  * @brief Class destructor.
167  *
168  * Decrements the ref count and deletes if necessary the dumb pointer.
169  */
170  ~RefPtr();
171 
172  ///@}
173  // ============================================================================
174  /// @name Accessors / Modifiers
175  // ============================================================================
176  /// @{
177 
178  /**
179  * @brief Checks whether a RefPtr points toward something.
180  *
181  * This method enables writing code like @c if (refptr) perform_operation()
182  */
183  operator bool() const;
184 
185  /**
186  * @brief Makes the smart pointer point to 0.
187  *
188  * If necessary, the dumb pointer previously pointed to by the RefPtr is
189  * deallocated. In this case, an exception may be thrown by the destructor
190  * of the object pointed to. But, even in this case, the RefPtr guarrantees
191  * that after the completion of this method, the RefPtr will point toward
192  * 0.
193  */
194  void clear();
195 
196  /**
197  * @brief Returns the number of smart pointer referencing the contained
198  * pointer.
199  */
200  unsigned int refCount() const;
201 
202  /// @}
203  // ============================================================================
204  /// @name Operators
205  // ============================================================================
206  /// @{
207 
208  /**
209  * @brief Copy operator.
210  *
211  * The operator= may throw exceptions when the dumb pointer previously
212  * pointed to by the RefPtr is deallocated (that is, the destructor of the
213  * object pointed to may throw an exception). However, even when this
214  * occurs, the RefPtr guarrantees that the copy operation is correctly
215  * performed, that is, after the completion of the function, the RefPtr
216  * points to the same element as from.
217  *
218  * @param from The smart pointer we wish to make a copy.
219  * @return Returns this gum::RefPtr.
220  */
221  RefPtr< Val >& operator=(const RefPtr< Val >& from);
222 
223  /**
224  * @brief Copy operator.
225  *
226  * The operator= may throw exceptions when the dumb pointer previously
227  * pointed to by the RefPtr is deallocated (that is, the destructor of the
228  * object pointed to may throw an exception). However, even when this
229  * occurs, the RefPtr guarrantees that its state is coherent: either it
230  * could succeed to encapsulate the dumb pointer and this one is referenced
231  * once, or even encapsulating the new pointer failed and the RefPtr points
232  * toward the 0 pointer.
233  *
234  * @param from the dumb pointer we wish to encapsulate.
235  * @return Returns this gum::RefPtr.
236  */
237 
238  RefPtr< Val >& operator=(Val* from);
239 
240  /**
241  * @brief Copy operator for downcastable pointers.
242  *
243  * The operator= may throw exceptions when the dumb pointer previously
244  * pointed to by the RefPtr is deallocated (that is, the destructor of the
245  * object pointed to may throw an exception). However, even when this
246  * occurs, the RefPtr guarrantees that the copy operation is correctly
247  * performed, that is, after the completion of the function, the RefPtr
248  * points to the same element as from.
249  *
250  * @tparam DownVal The downcastable type.
251  * @param from the smart pointer we wish to make a copy.
252  * @return Returns this gum::RefPtr.
253  */
254  template < typename DownVal >
255  RefPtr< Val >& operator=(const RefPtr< DownVal >& from);
256 
257  /**
258  * @brief Checks whether two RefPtr<Val> are smart pointers for the same
259  * element.
260  *
261  * "Pointing toward the same element" is a little ambiguous: it does not
262  * mean that the smart pointers are pointing toward the same Val instance
263  * as several RefPtr<Val> created by the constructor with *val may point
264  * toward the same val element while being unrelated (they do not share the
265  * same reference). Instead, it means that the two smart pointers share the
266  * same reference counter, i.e., that at least one of the two smarts
267  * pointers has been created using the copy operator. As a consequence both
268  * pointers point toward the same Val instance (but the converse is false).
269  *
270  * @param from The gum::RefPtr to test for equality.
271  * @return Returns true if this and from are equal.
272  */
273  bool operator==(const RefPtr< Val >& from) const;
274 
275  /**
276  * @brief Checks whether two RefPtr<Val> are smart pointers for different
277  * elements.
278  *
279  * Returns true if either the dumb pointers the smart pointers encapsulate
280  * are different or the reference counters are different (i.e., the smart
281  * pointers are not related through copy operators).
282  *
283  * @param from The gum::RefPtr to test for inequality.
284  * @return Returns true if this and from differ.
285  */
286  bool operator!=(const RefPtr< Val >& from) const;
287 
288  /**
289  * @brief Dereferencing operator.
290  *
291  * This operator allows developers to write code like @c refptr->member().
292  * @return Returns a pointer over the value referenced by this gum::RefPtr.
293  * @throws NullElement Raised whenever the smart pointer points toward 0.
294  */
295  Val* operator->() const;
296 
297  /**
298  * @brief Dereferencing operator.
299  *
300  * This operator is provided for convenience but you should prefer using
301  * operator -> as this is the syntax you would use with the dumb pointer.
302  * Note however that it might be useful for built-in types such as int.
303  *
304  * @return Returns a reference over the value referenced by this
305  * gum::RefPtr.
306  * @throw NullElement Raised whenever the RefPtr points to 0.
307  */
308  Val& operator*();
309 
310  /**
311  * @brief Const dereferencing operator.
312  *
313  * This operator is provided for convenience but you should prefer using
314  * operator -> as this is the syntax you would use with the dumb pointer.
315  * Note however that it might be useful for built-in types such as int.
316  *
317  * @return Returns a constant reference over the value referenced by this
318  * gum::RefPtr.
319  * @throw NullElement Raised whenever the RefPtr points to 0.
320  */
321  const Val& operator*() const;
322 
323  /// @}
324  // ============================================================================
325  /// @name Internals
326  // ============================================================================
327  private:
328  /// A friend to allow downcastings.
329  template < typename T >
330  friend class RefPtr;
331 
332  /// A friend for hashing quickly ref pointers.
333  template < typename T >
334  friend class HashFunc;
335 
336  /// The dumb pointer encapsulated into the "smart" pointer.
337  Val* _val_;
338 
339  /// A reference counter on *val.
340  unsigned int* _refcount_;
341 
342  /// A function to remove the content of the smart pointer, if any.
343  void _destroy_(unsigned int*, Val*);
344 
345  /// A function to return the refcount pointer.
346  unsigned int* _refCountPtr_() const;
347  };
348 
349 } /* namespace gum */
350 
351 
352 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
353 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
354 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
355 extern template class gum::RefPtr< int >;
356 # endif
357 # endif
358 #endif
359 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
360 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
361 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
362 extern template class gum::RefPtr< long >;
363 # endif
364 # endif
365 #endif
366 
367 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
368 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
369 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
370 extern template class gum::RefPtr< double >;
371 # endif
372 # endif
373 #endif
374 
375 
376 // always include the tpl_.h as it contains only templates
377 #include <agrum/tools/core/refPtr_tpl.h>
378 
379 #endif /* GUM_REFPTR_H */
RefPtr< Val > & operator=(const RefPtr< Val > &from)
Copy operator.
Definition: refPtr_tpl.h:79
friend class RefPtr
A friend to allow downcastings.
Definition: refPtr.h:330
~RefPtr()
Class destructor.
Definition: refPtr_tpl.h:165
Val * operator->() const
Dereferencing operator.
Definition: refPtr_tpl.h:205
RefPtr< Val > & operator=(Val *from)
Copy operator.
Definition: refPtr_tpl.h:104
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
operator bool() const
Checks whether a RefPtr points toward something.
Definition: refPtr_tpl.h:214
friend void swap(RefPtr< Val > &, RefPtr< Val > &)
The swap function must access to gum::RefPtr private parts.
Definition: refPtr_tpl.h:251
RefPtr(const RefPtr< DownVal > &from)
Copy constructor for downcastable pointers.
friend class HashFunc
A friend for hashing quickly ref pointers.
Definition: refPtr.h:334
unsigned int * _refcount_
A reference counter on *val.
Definition: refPtr.h:340
const Val & operator*() const
Const dereferencing operator.
Definition: refPtr_tpl.h:196
bool operator!=(const RefPtr< Val > &from) const
Checks whether two RefPtr<Val> are smart pointers for different elements.
Definition: refPtr_tpl.h:180
RefPtr< Val > & operator=(const RefPtr< DownVal > &from)
Copy operator for downcastable pointers.
bool operator==(const RefPtr< Val > &from) const
Checks whether two RefPtr<Val> are smart pointers for the same element.
Definition: refPtr_tpl.h:173
unsigned int * _refCountPtr_() const
A function to return the refcount pointer.
Definition: refPtr_tpl.h:244
void clear()
Makes the smart pointer point to 0.
Definition: refPtr_tpl.h:221
RefPtr(Val *val=0)
Default constructor.
Definition: refPtr_tpl.h:35
Val * _val_
The dumb pointer encapsulated into the "smart" pointer.
Definition: refPtr.h:337
Val & operator*()
Dereferencing operator.
Definition: refPtr_tpl.h:187
void swap(RefPtr< Val > &ptr1, RefPtr< Val > &ptr2)
Swap the contents of two RefPtr.
Definition: refPtr_tpl.h:251
RefPtr(const RefPtr< Val > &from)
Copy constructor.
Definition: refPtr_tpl.h:42
void _destroy_(unsigned int *, Val *)
A function to remove the content of the smart pointer, if any.
Definition: refPtr_tpl.h:63
unsigned int refCount() const
Returns the number of smart pointer referencing the contained pointer.
Definition: refPtr_tpl.h:235