c++-gtk-utils
shared_ptr.h
Go to the documentation of this file.
1 /* Copyright (C) 2004 to 2012 Chris Vine
2 
3 The library comprised in this file or of which this file is part is
4 distributed by Chris Vine under the GNU Lesser General Public
5 License as follows:
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Lesser General Public License
9  as published by the Free Software Foundation; either version 2.1 of
10  the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License, version 2.1, for more details.
16 
17  You should have received a copy of the GNU Lesser General Public
18  License, version 2.1, along with this library (see the file LGPL.TXT
19  which came with this source code package in the c++-gtk-utils
20  sub-directory); if not, write to the Free Software Foundation, Inc.,
21  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 
23 However, it is not intended that the object code of a program whose
24 source code instantiates a template from this file or uses macros or
25 inline functions (of any length) should by reason only of that
26 instantiation or use be subject to the restrictions of use in the GNU
27 Lesser General Public License. With that in mind, the words "and
28 macros, inline functions and instantiations of templates (of any
29 length)" shall be treated as substituted for the words "and small
30 macros and small inline functions (ten lines or less in length)" in
31 the fourth paragraph of section 5 of that licence. This does not
32 affect any other reason why object code may be subject to the
33 restrictions in that licence (nor for the avoidance of doubt does it
34 affect the application of section 2 of that licence to modifications
35 of the source code in this file).
36 
37 */
38 
39 #ifndef CGU_SHARED_PTR_H
40 #define CGU_SHARED_PTR_H
41 
42 // define this if, instead of GLIB atomic funcions/memory barriers,
43 // you want to use a (slower) mutex to lock the reference count in the
44 // SharedLockPtr class (however, if wanted, this is best left for
45 // definition in the user code)
46 /* #define CGU_SHARED_LOCK_PTR_USE_MUTEX 1 */
47 
48 #include <utility> // for std::move and std::swap
49 #include <exception>
50 #include <new>
51 #include <functional> // for std::less and std::hash<T*>
52 #include <cstddef> // for std::size_t
53 
54 #ifdef CGU_SHARED_LOCK_PTR_USE_MUTEX
55 #include <c++-gtk-utils/mutex.h>
56 #else
57 #include <glib.h>
58 #endif
59 
61 
62 /**
63  * @addtogroup handles handles and smart pointers
64  */
65 
66 namespace Cgu {
67 
68 /**
69  * @class SharedPtrError shared_ptr.h c++-gtk-utils/shared_ptr.h
70  * @brief This is an exception struct thrown as an alternative to
71  * deleting a managed object when internal memory allocation for
72  * SharedPtr or SharedLockPtr fails in their reset() method or in
73  * their constructor which takes a pointer.
74  * @ingroup handles
75  * @sa SharedPtr SharedLockPtr SharedPtrAllocFail
76  *
77  * This is an exception struct thrown as an alternative to deleting a
78  * managed object when SharedPtr<T>::SharedPtr(T*),
79  * SharedLockPtr<T>::SharedLockPtr(T*), SharedPtr<T>::reset(T*) or
80  * SharedLockPtr<T>::reset(T*), would otherwise throw std::bad_alloc.
81  * To make those methods do that, Cgu::SharedPtrAllocFail::leave is
82  * passed as their second argument.
83  *
84  * If the exception is thrown, the struct has a member 'obj' of type
85  * T*, which is a pointer to the object originally passed to those
86  * methods, so the user can deal with it appropriately. This enables
87  * the result of the new expression to be passed directly as the
88  * argument to those methods without giving rise to a resource leak,
89  * as in:
90  *
91  * @code
92  * using namespace Cgu;
93  * SharedPtr<T> s; // doesn't throw
94  * try {
95  * s.reset(new T, SharedPtrAllocFail::leave); // both T allocation and reset() might throw
96  * }
97  * catch (std::bad_alloc&) {
98  * ...
99  * }
100  * catch (SharedPtrError<T>& e) {
101  * e.obj->do_something();
102  * ...
103  * }
104  * ...
105  * @endcode
106  *
107  * As above, a catch block will need to deal with std::bad_alloc (if
108  * the call to the new expression when creating the T object fails)
109  * as well as SharedPtrError (if the call to the new expression in
110  * the reset() method fails after a valid T object has been
111  * constructed).
112  */
113 
114 template <class T> struct SharedPtrError: public std::exception {
115  T* obj;
116  virtual const char* what() const throw() {return "SharedPtrError\n";}
117  SharedPtrError(T* p): obj(p) {}
118 };
119 
120 /**
121  * enum Cgu::SharedPtrAllocFail::Leave
122  * The enumerator Cgu::SharedPtrAllocFail::leave is passed as the
123  * second argument of the reset() method of SharedPtr or
124  * SharedLockPtr, or in their constructor which takes a pointer, in
125  * order to prevent the method deleting the object passed to it if
126  * reset() fails internally because of memory exhaustion.
127  * @ingroup handles
128  */
129 namespace SharedPtrAllocFail {
130  enum Leave {leave};
131 }
132 
133 
134 /**
135  * @class SharedPtr shared_ptr.h c++-gtk-utils/shared_ptr.h
136  * @brief This is a smart pointer for managing the lifetime of objects
137  * allocated on freestore.
138  * @ingroup handles
139  * @sa SharedLockPtr SharedPtrError
140  *
141  * This is a smart pointer for managing the lifetime of objects
142  * allocated on freestore with the new expression. A managed object
143  * will be deleted when the last SharedPtr referencing it is
144  * destroyed.
145  *
146  * @b Comparison @b with @b std::shared_ptr
147  *
148  * Most of the things that can be done by this class can be done by
149  * using std::shared_ptr in C++11, but this class is retained in the
150  * c++-gtk-utils library not only to retain compatibility with series
151  * 1.2 of the library, but also to cater for some cases not met (or
152  * not so easily met) by std::shared_ptr:
153  *
154  * (i) Glib memory slices provide an efficient small object allocator
155  * (they are likely to be significantly more efficient than global
156  * operator new()/new[](), which generally hand off to malloc(), and
157  * whilst malloc() is good for large block allocations it is generally
158  * poor as a small object allocator). Internal Cgu::SharedPtr
159  * allocation using glib memory slices can be achieved by compiling
160  * the library with the --with-glib-memory-slices-no-compat
161  * configuration option.
162  *
163  * (ii) If glib memory slices are not used (which do not throw),
164  * constructing a shared pointer for a new managed object (or calling
165  * reset() for a new managed object) might throw if internal
166  * allocation fails. Although by default the Cgu::SharedPtr
167  * implementation will delete the new managed object in such a case,
168  * it also provides an alternative constructor and reset() method
169  * which instead enable the new object to be accessed via the thrown
170  * exception object so that user code can decide what to do;
171  * std::shared_ptr deletes the new object in every case.
172  *
173  * (iii) A user can explicitly state whether the shared pointer object
174  * is to have atomic increment and decrement-and-test with respect to
175  * the reference count so that the reference count is thread safe
176  * ('no' in the case of Cgu::SharedPtr, and 'yes' in the case of
177  * Cgu::SharedLockPtr). Using atomic functions is unnecessary if the
178  * managed object concerned is only addressed in one thread (and might
179  * cause unwanted cache flushing in certain circumstances).
180  * std::shared_ptr will generally always use atomic functions with
181  * respect to its reference count in a multi-threaded program.
182  *
183  * In favour of C++11's std::shared_ptr, it has an associated
184  * std::make_shared() factory function which will construct both the
185  * referenced object and the shared pointer's reference count within a
186  * single memory block when the first shared pointer managing a
187  * particular object is constructed. Cgu::SharedPtr and
188  * Cgu::SharedLockPtr always allocate these separately, but this is
189  * partly mitigated by the use of glib memory slices to allocate the
190  * reference count where the --with-glib-memory-slices-no-compat
191  * configuration option is chosen.
192  *
193  * In addition, std::shared_ptr has an associated std::weak_ptr class,
194  * which Cgu::SharedPtr does not (there is a Cgu::GobjWeakHandle
195  * class, but that is cognate with Cgu::GobjHandle and is only usable
196  * with GObjects).
197  */
198 
199 template <class T> class SharedPtr {
200 
201 #ifndef DOXYGEN_PARSING
202  struct RefItems {
203  unsigned int* ref_count_p;
204  T* obj_p;
205  } ref_items;
206 #endif
207 
208  void unreference() {
209  if (!ref_items.ref_count_p) return;
210  --(*ref_items.ref_count_p);
211  if (*ref_items.ref_count_p == 0) {
212 #ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
213  g_slice_free(unsigned int, ref_items.ref_count_p);
214 #else
215  delete ref_items.ref_count_p;
216 #endif
217  delete ref_items.obj_p;
218  }
219  }
220 
221  void reference() {
222  if (!ref_items.ref_count_p) return;
223  ++(*ref_items.ref_count_p);
224  }
225 
226 public:
227 /**
228  * Constructor taking an unmanaged object.
229  * @param ptr The object which the SharedPtr is to manage (if any).
230  * @exception std::bad_alloc This constructor will not throw if the
231  * 'ptr' argument has a NULL value (the default), otherwise it might
232  * throw std::bad_alloc if memory is exhausted and the system throws
233  * in that case. If such an exception is thrown, this constructor is
234  * exception safe (it does not leak resources), but as well as
235  * cleaning itself up this constructor will also delete the managed
236  * object passed to it to avoid a memory leak. If such automatic
237  * deletion is not wanted in that case, use the version of this
238  * constructor taking a Cgu::SharedPtrAllocFail::Leave tag argument.
239  * @note std::bad_alloc will not be thrown if the library has been
240  * installed using the --with-glib-memory-slices-no-compat
241  * configuration option: instead glib will terminate the program if it
242  * is unable to obtain memory from the operating system.
243  */
244  explicit SharedPtr(T* ptr = 0) {
245 
246  if ((ref_items.obj_p = ptr)) { // not NULL
247 #ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
248  ref_items.ref_count_p = g_slice_new(unsigned int);
249  *ref_items.ref_count_p = 1;
250 #else
251  try {
252  ref_items.ref_count_p = new unsigned int(1);
253  }
254  catch (...) {
255  delete ptr; // if allocating the int referenced by ref_items.ref_count_p
256  // has failed then delete the object to be referenced to
257  // avoid a memory leak
258  throw;
259  }
260 #endif
261  }
262  else ref_items.ref_count_p = 0;
263  }
264 
265 /**
266  * Constructor taking an unmanaged object.
267  * @param ptr The object which the SharedPtr is to manage.
268  * @param tag Passing the tag emumerator
269  * Cgu::SharedPtrAllocFail::leave causes this constructor not to
270  * delete the new managed object passed as the 'ptr' argument in the
271  * event of internal allocation in this method failing because of
272  * memory exhaustion (in that event, Cgu::SharedPtrError will be
273  * thrown).
274  * @exception Cgu::SharedPtrError This constructor might throw
275  * Cgu::SharedPtrError if memory is exhausted and the system would
276  * otherwise throw std::bad_alloc in that case. This constructor is
277  * exception safe (it does not leak resources), and if such an
278  * exception is thrown it will clean itself up, but it will not
279  * attempt to delete the new managed object passed to it. Access to
280  * the object passed to the 'ptr' argument can be obtained via the
281  * thrown Cgu::SharedPtrError object.
282  * @note 1. On systems with over-commit/lazy-commit combined with
283  * virtual memory (swap), it is rarely useful to check for memory
284  * exhaustion, so in those cases this version of the constructor will
285  * not be useful.
286  * @note 2. If the library has been installed using the
287  * --with-glib-memory-slices-no-compat configuration option this
288  * version of the constructor will also not be useful: instead glib
289  * will terminate the program if it is unable to obtain memory from
290  * the operating system.
291  */
293 
294  if ((ref_items.obj_p = ptr)) { // not NULL
295 #ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
296  ref_items.ref_count_p = g_slice_new(unsigned int);
297  *ref_items.ref_count_p = 1;
298 #else
299  try {
300  ref_items.ref_count_p = new unsigned int(1);
301  }
302  catch (std::bad_alloc&) { // as we are not rethrowing, make NPTL friendly
303  throw SharedPtrError<T>(ptr);
304  }
305 #endif
306  }
307  else ref_items.ref_count_p = 0;
308  }
309 
310 /**
311  * Causes the SharedPtr to cease to manage its managed object (if
312  * any), deleting it if this is the last SharedPtr object managing it.
313  * If the argument passed is not NULL, the SharedPtr object will
314  * manage the new object passed (which must not be managed by any
315  * other SharedPtr object). This method is exception safe, but see
316  * the comments below on std::bad_alloc.
317  * @param ptr NULL (the default), or a new unmanaged object to manage.
318  * @exception std::bad_alloc This method will not throw if the 'ptr'
319  * argument has a NULL value (the default) and the destructor of a
320  * managed object does not throw, otherwise it might throw
321  * std::bad_alloc if memory is exhausted and the system throws in that
322  * case. Note that if such an exception is thrown then this method
323  * will do nothing (it is strongly exception safe and will continue to
324  * manage the object it was managing prior to the call), except that
325  * it will delete the new managed object passed to it to avoid a
326  * memory leak. If such automatic deletion in the event of such an
327  * exception is not wanted, use the reset() method taking a
328  * Cgu::SharedPtrAllocFail::Leave tag type as its second argument.
329  * @note std::bad_alloc will not be thrown if the library has been
330  * installed using the --with-glib-memory-slices-no-compat
331  * configuration option: instead glib will terminate the program if it
332  * is unable to obtain memory from the operating system.
333  */
334  void reset(T* ptr = 0) {
335  SharedPtr tmp(ptr);
336  std::swap(ref_items, tmp.ref_items);
337  }
338 
339 /**
340  * Causes the SharedPtr to cease to manage its managed object (if
341  * any), deleting it if this is the last SharedPtr object managing it.
342  * The SharedPtr object will manage the new object passed (which must
343  * not be managed by any other SharedPtr object). This method is
344  * exception safe, but see the comments below on Cgu::SharedPtrError.
345  * @param ptr A new unmanaged object to manage (if no new object is to
346  * be managed, use the version of reset() taking a default value of
347  * NULL).
348  * @param tag Passing the tag emumerator
349  * Cgu::SharedPtrAllocFail::leave causes this method not to delete the
350  * new managed object passed as the 'ptr' argument in the event of
351  * internal allocation in this method failing because of memory
352  * exhaustion (in that event, Cgu::SharedPtrError will be thrown).
353  * @exception Cgu::SharedPtrError This method might throw
354  * Cgu::SharedPtrError if memory is exhausted and the system would
355  * otherwise throw std::bad_alloc in that case. Note that if such an
356  * exception is thrown then this method will do nothing (it is
357  * strongly exception safe and will continue to manage the object it
358  * was managing prior to the call), and it will not attempt to delete
359  * the new managed object passed to it. Access to the object passed
360  * to the 'ptr' argument can be obtained via the thrown
361  * Cgu::SharedPtrError object.
362  * @note 1. On systems with over-commit/lazy-commit combined with
363  * virtual memory (swap), it is rarely useful to check for memory
364  * exhaustion, so in those cases this version of the reset() method
365  * will not be useful.
366  * @note 2. If the library has been installed using the
367  * --with-glib-memory-slices-no-compat configuration option this
368  * version of the reset() method will also not be useful: instead glib
369  * will terminate the program if it is unable to obtain memory from
370  * the operating system.
371  */
373  SharedPtr tmp(ptr, tag);
374  std::swap(ref_items, tmp.ref_items);
375  }
376 
377  /**
378  * This copy constructor does not throw.
379  * @param sh_ptr The shared pointer to be copied.
380  */
381  SharedPtr(const SharedPtr& sh_ptr) {
382  ref_items = sh_ptr.ref_items;
383  reference();
384  }
385 
386  /**
387  * The move constructor does not throw. It has move semantics.
388  * @param sh_ptr The shared pointer to be moved.
389  */
390  SharedPtr(SharedPtr&& sh_ptr) {
391  ref_items = sh_ptr.ref_items;
392  sh_ptr.ref_items.ref_count_p = 0;
393  sh_ptr.ref_items.obj_p = 0;
394  }
395 
396  template <class U> friend class SharedPtr;
397 
398  /**
399  * A version of the copy constructor which enables pointer type
400  * conversion (assuming the type passed is implicitly type
401  * convertible to the managed type, such as a derived type). This
402  * copy constructor does not throw.
403  * @param sh_ptr The shared pointer to be copied.
404  */
405  template <class U> SharedPtr(const SharedPtr<U>& sh_ptr) {
406  // because we are allowing an implicit cast from derived to
407  // base class referenced object, we need to assign from each
408  // member of sh_ptr.ref_items separately
409  ref_items.ref_count_p = sh_ptr.ref_items.ref_count_p;
410  ref_items.obj_p = sh_ptr.ref_items.obj_p;
411  reference();
412  }
413 
414  /**
415  * A version of the move constructor which enables pointer type
416  * conversion (assuming the type passed is implicitly type
417  * convertible to the managed type, such as a derived type). This
418  * move constructor does not throw.
419  * @param sh_ptr The shared pointer to be moved.
420  */
421  template <class U> SharedPtr(SharedPtr<U>&& sh_ptr) {
422  // because we are allowing an implicit cast from derived to
423  // base class referenced object, we need to assign from each
424  // member of sh_ptr.ref_items separately
425  ref_items.ref_count_p = sh_ptr.ref_items.ref_count_p;
426  ref_items.obj_p = sh_ptr.ref_items.obj_p;
427  sh_ptr.ref_items.ref_count_p = 0;
428  sh_ptr.ref_items.obj_p = 0;
429  }
430 
431  /**
432  * This method (and so copy or move assignment) does not throw unless
433  * the destructor of a managed object throws.
434  * @param sh_ptr the assignor.
435  * @return The SharedPtr object after assignment.
436  */
437  // having a value type as the argument, rather than reference to const
438  // and then initialising a tmp object, gives the compiler more scope
439  // for optimisation, and also caters for r-values without a separate
440  // overload
442  std::swap(ref_items, sh_ptr.ref_items);
443  return *this;
444  }
445 
446  /**
447  * A version of the assignment operator which enables pointer type
448  * conversion (assuming the type passed is implicitly type
449  * convertible to the managed type, such as a derived type). This
450  * method does not throw unless the destructor of a managed object
451  * throws.
452  * @param sh_ptr the assignor.
453  * @return The SharedPtr object after assignment.
454  */
455  template <class U> SharedPtr& operator=(const SharedPtr<U>& sh_ptr) {
456  return operator=(SharedPtr(sh_ptr));
457  }
458 
459  /**
460  * A version of the operator for move assignment which enables
461  * pointer type conversion (assuming the type passed is implicitly
462  * type convertible to the managed type, such as a derived type).
463  * This method does not throw unless the destructor of a managed
464  * object throws.
465  * @param sh_ptr the shared pointer to be moved.
466  * @return The SharedPtr object after the move operation.
467  */
468  template <class U> SharedPtr& operator=(SharedPtr<U>&& sh_ptr) {
469  return operator=(SharedPtr(std::move(sh_ptr)));
470  }
471 
472  /**
473  * This method does not throw.
474  * @return A pointer to the managed object (or NULL if none is
475  * managed).
476  */
477  T* get() const {return ref_items.obj_p;}
478 
479  /**
480  * This method does not throw.
481  * @return A reference to the managed object.
482  */
483  T& operator*() const {return *ref_items.obj_p;}
484 
485  /**
486  * This method does not throw.
487  * @return A pointer to the managed object (or NULL if none is
488  * managed).
489  */
490  T* operator->() const {return ref_items.obj_p;}
491 
492  /**
493  * This method does not throw.
494  * @return The number of SharedPtr objects referencing the managed
495  * object (or 0 if none is managed by this SharedPtr).
496  */
497  unsigned int get_refcount() const {return (ref_items.ref_count_p) ? *ref_items.ref_count_p : 0;}
498 
499  /**
500  * The destructor does not throw unless the destructor of a managed
501  * object throws - that should never happen.
502  */
503  ~SharedPtr() {unreference();}
504 };
505 
506 /**
507  * @class SharedLockPtr shared_ptr.h c++-gtk-utils/shared_ptr.h
508  * @brief This is a smart pointer for managing the lifetime of objects
509  * allocated on freestore, with a thread safe reference count.
510  * @ingroup handles
511  * @sa SharedPtr SharedPtrError
512  *
513  * Class SharedLockPtr is a version of the shared pointer class which
514  * includes locking so that it can be accessed in multiple threads
515  * (although the word Lock is in the title, by default it uses glib
516  * atomic functions to access the reference count rather than a mutex,
517  * so the overhead should be very small). Note that only the
518  * reference count is protected, so this is thread safe in the sense
519  * in which a raw pointer is thread safe. A shared pointer accessed
520  * in one thread referencing a particular object is thread safe as
521  * against another shared pointer accessing the same object in a
522  * different thread. It is thus suitable for use in different Std C++
523  * containers which exist in different threads but which contain
524  * shared objects by reference. But:
525  *
526  * 1. If the referenced object is to be modified in one thread and
527  * read or modified in another thread an appropriate mutex for the
528  * referenced object is required (unless that referenced object
529  * does its own locking).
530  *
531  * 2. If the same instance of shared pointer is to be modified in one
532  * thread (by assigning to the pointer so that it references a
533  * different object, or by moving from it), and copied (assigned
534  * from or used as the argument of a copy constructor), accessed,
535  * destroyed or modified in another thread, a mutex for that
536  * instance of shared pointer is required.
537  *
538  * 3. Objects referenced by shared pointers which are objects for
539  * which POSIX provides no guarantees (in the main, those which
540  * are not built-in types), such as strings and similar
541  * containers, may not support concurrent reads in different
542  * threads. That depends on the library implementation concerned.
543  * If that is the case, a mutex for the referenced object will
544  * also be required when reading any given instance of such an
545  * object in more than one thread by dereferencing any shared
546  * pointers referencing it (and indeed, when not using shared
547  * pointers at all).
548  *
549  * As mentioned, by default glib atomic functions are used to provide
550  * thread-safe manipulation of the reference count. However, a
551  * library user can define the symbol CGU_SHARED_LOCK_PTR_USE_MUTEX
552  * before shared_ptr.h is parsed so as to use mutexes instead, which
553  * might be useful for some debugging purposes.
554  *
555  * @b Comparison @b with @b std::shared_ptr
556  *
557  * Most of the things that can be done by this class can be done by
558  * using std::shared_ptr in C++11, but this class is retained in the
559  * c++-gtk-utils library not only to retain compatibility with series
560  * 1.2 of the library, but also to cater for some cases not met (or
561  * not so easily met) by std::shared_ptr:
562  *
563  * (i) Glib memory slices provide an efficient small object allocator
564  * (they are likely to be significantly more efficient than global
565  * operator new()/new[](), which generally hand off to malloc(), and
566  * whilst malloc() is good for large block allocations it is generally
567  * poor as a small object allocator). Internal Cgu::SharedLockPtr
568  * allocation using glib memory slices can be achieved by compiling
569  * the library with the --with-glib-memory-slices-no-compat
570  * configuration option.
571  *
572  * (ii) If glib memory slices are not used (which do not throw),
573  * constructing a shared pointer for a new managed object (or calling
574  * reset() for a new managed object) might throw if internal
575  * allocation fails. Although by default the Cgu::SharedLockPtr
576  * implementation will delete the new managed object in such a case,
577  * it also provides an alternative constructor and reset() method
578  * which instead enable the new object to be accessed via the thrown
579  * exception object so that user code can decide what to do;
580  * std::shared_ptr deletes the new object in every case.
581  *
582  * (iii) A user can explicitly state whether the shared pointer object
583  * is to have atomic increment and decrement-and-test with respect to
584  * the reference count so that the reference count is thread safe
585  * ('no' in the case of Cgu::SharedPtr, and 'yes' in the case of
586  * Cgu::SharedLockPtr). Using atomic functions is unnecessary if the
587  * managed object concerned is only addressed in one thread (and might
588  * cause unwanted cache flushing in certain circumstances).
589  * std::shared_ptr will generally always use atomic functions with
590  * respect to its reference count in a multi-threaded program.
591  *
592  * In favour of C++11's std::shared_ptr, it has an associated
593  * std::make_shared() factory function which will construct both the
594  * referenced object and the shared pointer's reference count within a
595  * single memory block when the first shared pointer managing a
596  * particular object is constructed. Cgu::SharedPtr and
597  * Cgu::SharedLockPtr always allocate these separately, but this is
598  * partly mitigated by the use of glib memory slices to allocate the
599  * reference count where the --with-glib-memory-slices-no-compat
600  * configuration option is chosen.
601  *
602  * In addition, std::shared_ptr has an associated std::weak_ptr class,
603  * which Cgu::SharedLockPtr does not (there is a Cgu::GobjWeakHandle
604  * class, but that is cognate with Cgu::GobjHandle and is only usable
605  * with GObjects), and shared_ptr objects also have some atomic store,
606  * load and exchange functions provided for them which enable
607  * concurrent modifications of the same instance of shared_ptr in
608  * different threads to have defined results.
609  */
610 
611 template <class T> class SharedLockPtr {
612 
613 #ifndef DOXYGEN_PARSING
614  struct RefItems {
615 #ifdef CGU_SHARED_LOCK_PTR_USE_MUTEX
616  Thread::Mutex* mutex_p;
617  unsigned int* ref_count_p;
618 #else
619  gint* ref_count_p;
620 #endif
621  T* obj_p;
622  } ref_items;
623 #endif
624 
625  // SharedLockPtr<T>::unreference() does not throw if the destructor of the
626  // contained object does not throw, because Thread::Mutex::~Mutex(),
627  // Thread::Mutex::lock() and Thread::Mutex::unlock() do not throw
628  void unreference() {
629  // we can (and should) check whether ref_items.ref_count_p is NULL without
630  // a lock, because that member is specific to this SharedLockPtr object.
631  // Only the integer pointed to by it is shared amongst SharedLockPtr
632  // objects and requires locking
633  if (!ref_items.ref_count_p) return;
634 #ifdef CGU_SHARED_LOCK_PTR_USE_MUTEX
635  ref_items.mutex_p->lock();
636  --(*ref_items.ref_count_p);
637  if (*ref_items.ref_count_p == 0) {
638 # ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
639  g_slice_free(unsigned int, ref_items.ref_count_p);
640 # else
641  delete ref_items.ref_count_p;
642 # endif
643  ref_items.mutex_p->unlock();
644  delete ref_items.mutex_p;
645  delete ref_items.obj_p;
646  }
647  else ref_items.mutex_p->unlock();
648 #else
649  if (g_atomic_int_dec_and_test(ref_items.ref_count_p)) {
650 # ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
651  g_slice_free(gint, ref_items.ref_count_p);
652 # else
653  delete ref_items.ref_count_p;
654 # endif
655  delete ref_items.obj_p;
656  }
657 #endif
658  }
659 
660  // SharedLockPtr<T>::reference() does not throw because
661  // Thread::Mutex::Lock::Lock() and Thread::Mutex::Lock::~Lock() do not throw
662  void reference() {
663  // we can (and should) check whether ref_items.ref_count_p is NULL without
664  // a lock, because that member is specific to this SharedLockPtr object.
665  // Only the integer pointed to by it is shared amongst SharedLockPtr
666  // objects and requires locking
667  if (!ref_items.ref_count_p) return;
668 #ifdef CGU_SHARED_LOCK_PTR_USE_MUTEX
669  Thread::Mutex::Lock lock(*ref_items.mutex_p);
670  ++(*ref_items.ref_count_p);
671 #else
672  g_atomic_int_inc(ref_items.ref_count_p);
673 #endif
674  }
675 
676 public:
677 /**
678  * Constructor taking an unmanaged object.
679  * @param ptr The object which the SharedLockPtr is to manage (if
680  * any).
681  * @exception std::bad_alloc This constructor will not throw if the
682  * 'ptr' argument has a NULL value (the default), otherwise it might
683  * throw std::bad_alloc if memory is exhausted and the system throws
684  * in that case. If such an exception is thrown, this constructor is
685  * exception safe (it does not leak resources), but as well as
686  * cleaning itself up this constructor will also delete the managed
687  * object passed to it to avoid a memory leak. If such automatic
688  * deletion is not wanted in that case, use the version of this
689  * constructor taking a Cgu::SharedPtrAllocFail::Leave tag argument.
690  * @note 1. std::bad_alloc will not be thrown if the library has been
691  * installed using the --with-glib-memory-slices-no-compat
692  * configuration option: instead glib will terminate the program if it
693  * is unable to obtain memory from the operating system.
694  * @note 2. By default, glib atomic functions are used to provide
695  * thread-safe manipulation of the reference count. However, a
696  * library user can define the symbol CGU_SHARED_LOCK_PTR_USE_MUTEX
697  * before shared_ptr.h is parsed so as to use mutexes instead, which
698  * might be useful for some debugging purposes. Were she to do so,
699  * Cgu::Thread::MutexError might be thrown by this constructor if
700  * initialization of the mutex fails, but it is usually not worth
701  * checking for this.
702  */
703  explicit SharedLockPtr(T* ptr = 0) {
704 
705  if ((ref_items.obj_p = ptr)) { // not NULL
706 #ifdef CGU_SHARED_LOCK_PTR_USE_MUTEX
707  try {
708  ref_items.mutex_p = new Thread::Mutex;
709  }
710  catch (...) {
711  delete ptr; // if allocating the object referenced by ref_items.mutex_p
712  // has failed then delete the object to be referenced to
713  // avoid a memory leak
714  throw;
715  }
716 # ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
717  ref_items.ref_count_p = g_slice_new(unsigned int);
718  *ref_items.ref_count_p = 1;
719 # else
720  try {
721  ref_items.ref_count_p = new unsigned int(1);
722  }
723  catch (...) {
724  delete ref_items.mutex_p;
725  delete ptr;
726  throw;
727  }
728 # endif
729 #else
730 # ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
731  ref_items.ref_count_p = g_slice_new(gint);
732  *ref_items.ref_count_p = 1;
733 # else
734  try {
735  ref_items.ref_count_p = new gint(1);
736  }
737  catch (...) {
738  delete ptr; // if allocating the int referenced by ref_items.ref_count_p
739  // has failed then delete the object to be referenced to
740  // avoid a memory leak
741  throw;
742  }
743 # endif
744 #endif
745  }
746  else {
747 #ifdef CGU_SHARED_LOCK_PTR_USE_MUTEX
748  ref_items.mutex_p = 0; // make sure the value is valid as we may assign it
749 #endif
750  ref_items.ref_count_p = 0;
751  }
752  }
753 
754 /**
755  * Constructor taking an unmanaged object.
756  * @param ptr The object which the SharedLockPtr is to manage.
757  * @param tag Passing the tag emumerator
758  * Cgu::SharedPtrAllocFail::leave causes this constructor not to
759  * delete the new managed object passed as the 'ptr' argument in the
760  * event of internal allocation in this method failing because of
761  * memory exhaustion (in that event, Cgu::SharedPtrError will be
762  * thrown).
763  * @exception Cgu::SharedPtrError This constructor might throw
764  * Cgu::SharedPtrError if memory is exhausted and the system would
765  * otherwise throw std::bad_alloc in that case. This constructor is
766  * exception safe (it does not leak resources), and if such an
767  * exception is thrown it will clean itself up, but it will not
768  * attempt to delete the new managed object passed to it. Access to
769  * the object passed to the 'ptr' argument can be obtained via the
770  * thrown Cgu::SharedPtrError object.
771  * @note 1. On systems with over-commit/lazy-commit combined with
772  * virtual memory (swap), it is rarely useful to check for memory
773  * exhaustion, so in those cases this version of the constructor will
774  * not be useful.
775  * @note 2. If the library has been installed using the
776  * --with-glib-memory-slices-no-compat configuration option this
777  * version of the constructor will also not be useful: instead glib
778  * will terminate the program if it is unable to obtain memory from
779  * the operating system.
780  * @note 3. By default, glib atomic functions are used to provide
781  * thread-safe manipulation of the reference count. However, a
782  * library user can define the symbol CGU_SHARED_LOCK_PTR_USE_MUTEX
783  * before shared_ptr.h is parsed so as to use mutexes instead, which
784  * might be useful for some debugging purposes. Were she to do so,
785  * Cgu::SharedPtrError might be thrown by this constructor if
786  * initialization of the mutex fails (even if the
787  * --with-glib-memory-slices-no-compat configuration option is
788  * chosen), but it is usually not worth checking for such mutex
789  * initialization failure.
790  */
792 
793  if ((ref_items.obj_p = ptr)) { // not NULL
794 #ifdef CGU_SHARED_LOCK_PTR_USE_MUTEX
795  try {
796  ref_items.mutex_p = new Thread::Mutex;
797  }
798  catch (std::bad_alloc&) { // as we are not rethrowing, make NPTL friendly
799  throw SharedPtrError<T>(ptr);
800  }
801  catch (Thread::MutexError&) { // as we are not rethrowing, make NPTL friendly
802  throw SharedPtrError<T>(ptr);
803  }
804 # ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
805  ref_items.ref_count_p = g_slice_new(unsigned int);
806  *ref_items.ref_count_p = 1;
807 # else
808  try {
809  ref_items.ref_count_p = new unsigned int(1);
810  }
811  catch (std::bad_alloc&) {
812  delete ref_items.mutex_p;
813  throw SharedPtrError<T>(ptr);
814  }
815 # endif
816 #else
817 # ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
818  ref_items.ref_count_p = g_slice_new(gint);
819  *ref_items.ref_count_p = 1;
820 # else
821  try {
822  ref_items.ref_count_p = new gint(1);
823  }
824  catch (std::bad_alloc&) { // as we are not rethrowing, make NPTL friendly
825  throw SharedPtrError<T>(ptr);
826  }
827 # endif
828 #endif
829  }
830  else {
831 #ifdef CGU_SHARED_LOCK_PTR_USE_MUTEX
832  ref_items.mutex_p = 0; // make sure the value is valid as we may assign it
833 #endif
834  ref_items.ref_count_p = 0;
835  }
836  }
837 
838 /**
839  * Causes the SharedLockPtr to cease to manage its managed object (if
840  * any), deleting it if this is the last SharedLockPtr object managing
841  * it. If the argument passed is not NULL, the SharedLockPtr object
842  * will manage the new object passed (which must not be managed by any
843  * other SharedLockPtr object). This method is exception safe, but
844  * see the comments below on std::bad_alloc.
845  * @param ptr NULL (the default), or a new unmanaged object to manage.
846  * @exception std::bad_alloc This method will not throw if the 'ptr'
847  * argument has a NULL value (the default) and the destructor of a
848  * managed object does not throw, otherwise it might throw
849  * std::bad_alloc if memory is exhausted and the system throws in that
850  * case. Note that if such an exception is thrown then this method
851  * will do nothing (it is strongly exception safe and will continue to
852  * manage the object it was managing prior to the call), except that
853  * it will delete the new managed object passed to it to avoid a
854  * memory leak. If such automatic deletion in the event of such an
855  * exception is not wanted, use the reset() method taking a
856  * Cgu::SharedPtrAllocFail::Leave tag type as its second argument.
857  * @note 1. std::bad_alloc will not be thrown if the library has been
858  * installed using the --with-glib-memory-slices-no-compat
859  * configuration option: instead glib will terminate the program if it
860  * is unable to obtain memory from the operating system.
861  * @note 2. By default, glib atomic functions are used to provide
862  * thread-safe manipulation of the reference count. However, a
863  * library user can define the symbol CGU_SHARED_LOCK_PTR_USE_MUTEX
864  * before shared_ptr.h is parsed so as to use mutexes instead, which
865  * might be useful for some debugging purposes. Were she to do so,
866  * Cgu::Thread::MutexError might be thrown by this method if
867  * initialization of the mutex fails, but it is usually not worth
868  * checking for this.
869  * @note 3. A SharedLockPtr object protects its reference count but
870  * not the managed object or its other internals. The reset() method
871  * should not be called by one thread in respect of a particular
872  * SharedLockPtr object while another thread may be operating on,
873  * copying or dereferencing the same instance of SharedLockPtr. It is
874  * thread-safe as against another instance of SharedLockPtr managing
875  * the same object.
876  */
877  void reset(T* ptr = 0) {
878  SharedLockPtr tmp(ptr);
879  std::swap(ref_items, tmp.ref_items);
880  }
881 
882 /**
883  * Causes the SharedLockPtr to cease to manage its managed object (if
884  * any), deleting it if this is the last SharedLockPtr object managing
885  * it. The SharedLockPtr object will manage the new object passed
886  * (which must not be managed by any other SharedLockPtr object).
887  * This method is exception safe, but see the comments below on
888  * Cgu::SharedPtrError.
889  * @param ptr A new unmanaged object to manage (if no new object is to
890  * be managed, use the version of reset() taking a default value of
891  * NULL).
892  * @param tag Passing the tag emumerator
893  * Cgu::SharedPtrAllocFail::leave causes this method not to delete the
894  * new managed object passed as the 'ptr' argument in the event of
895  * internal allocation in this method failing because of memory
896  * exhaustion (in that event, Cgu::SharedPtrError will be thrown).
897  * @exception Cgu::SharedPtrError This method might throw
898  * Cgu::SharedPtrError if memory is exhausted and the system would
899  * otherwise throw std::bad_alloc in that case. Note that if such an
900  * exception is thrown then this method will do nothing (it is
901  * strongly exception safe and will continue to manage the object it
902  * was managing prior to the call), and it will not attempt to delete
903  * the new managed object passed to it. Access to the object passed
904  * to the 'ptr' argument can be obtained via the thrown
905  * Cgu::SharedPtrError object.
906  * @note 1. A SharedLockPtr object protects its reference count but
907  * not the managed object or its other internals. The reset() method
908  * should not be called by one thread in respect of a particular
909  * SharedLockPtr object while another thread may be operating on,
910  * copying or dereferencing the same instance of SharedLockPtr. It is
911  * thread-safe as against another instance of SharedLockPtr managing
912  * the same object.
913  * @note 2. On systems with over-commit/lazy-commit combined with
914  * virtual memory (swap), it is rarely useful to check for memory
915  * exhaustion, so in those cases this version of the reset() method
916  * will not be useful.
917  * @note 3. If the library has been installed using the
918  * --with-glib-memory-slices-no-compat configuration option this
919  * version of the reset() method will also not be useful: instead glib
920  * will terminate the program if it is unable to obtain memory from
921  * the operating system.
922  * @note 4. By default, glib atomic functions are used to provide
923  * thread-safe manipulation of the reference count. However, a
924  * library user can define the symbol CGU_SHARED_LOCK_PTR_USE_MUTEX
925  * before shared_ptr.h is parsed so as to use mutexes instead, which
926  * might be useful for some debugging purposes. Were she to do so,
927  * Cgu::SharedPtrError might be thrown by this method if
928  * initialization of the mutex fails (even if the
929  * --with-glib-memory-slices-no-compat configuration option is
930  * chosen), but it is usually not worth checking for such mutex
931  * initialization failure.
932  */
934  SharedLockPtr tmp(ptr, tag);
935  std::swap(ref_items, tmp.ref_items);
936  }
937 
938  /**
939  * This copy constructor does not throw.
940  * @param sh_ptr The shared pointer to be copied.
941  */
942  SharedLockPtr(const SharedLockPtr& sh_ptr) {
943  ref_items = sh_ptr.ref_items;
944  reference();
945  }
946 
947  /**
948  * The move constructor does not throw. It has move semantics.
949  * @param sh_ptr The shared pointer to be moved.
950  */
952  ref_items = sh_ptr.ref_items;
953 #ifdef CGU_SHARED_LOCK_PTR_USE_MUTEX
954  sh_ptr.ref_items.mutex_p = 0; // make sure the value is valid as we may assign it
955 #endif
956  sh_ptr.ref_items.ref_count_p = 0;
957  sh_ptr.ref_items.obj_p = 0;
958  }
959 
960  template <class U> friend class SharedLockPtr;
961 
962  /**
963  * A version of the copy constructor which enables pointer type
964  * conversion (assuming the type passed is implicitly type
965  * convertible to the managed type, such as a derived type). This
966  * copy constructor does not throw.
967  * @param sh_ptr The shared pointer to be copied.
968  */
969  template <class U> SharedLockPtr(const SharedLockPtr<U>& sh_ptr) {
970  // because we are allowing an implicit cast from derived to
971  // base class referenced object, we need to assign from each
972  // member of sh_ptr.ref_items separately
973 #ifdef CGU_SHARED_LOCK_PTR_USE_MUTEX
974  ref_items.mutex_p = sh_ptr.ref_items.mutex_p;
975 #endif
976  ref_items.ref_count_p = sh_ptr.ref_items.ref_count_p;
977  ref_items.obj_p = sh_ptr.ref_items.obj_p;
978  reference();
979  }
980 
981  /**
982  * A version of the move constructor which enables pointer type
983  * conversion (assuming the type passed is implicitly type
984  * convertible to the managed type, such as a derived type). This
985  * move constructor does not throw.
986  * @param sh_ptr The shared pointer to be moved.
987  */
988  template <class U> SharedLockPtr(SharedLockPtr<U>&& sh_ptr) {
989  // because we are allowing an implicit cast from derived to
990  // base class referenced object, we need to assign from each
991  // member of sh_ptr.ref_items separately
992 #ifdef CGU_SHARED_LOCK_PTR_USE_MUTEX
993  ref_items.mutex_p = sh_ptr.ref_items.mutex_p;
994 #endif
995  ref_items.ref_count_p = sh_ptr.ref_items.ref_count_p;
996  ref_items.obj_p = sh_ptr.ref_items.obj_p;
997 
998 #ifdef CGU_SHARED_LOCK_PTR_USE_MUTEX
999  sh_ptr.ref_items.mutex_p = 0; // make sure the value is valid as we may assign it
1000 #endif
1001  sh_ptr.ref_items.ref_count_p = 0;
1002  sh_ptr.ref_items.obj_p = 0;
1003  }
1004 
1005  /**
1006  * This method (and so copy or move assignment) does not throw unless
1007  * the destructor of a managed object throws.
1008  * @param sh_ptr the assignor.
1009  * @return The SharedLockPtr object after assignment.
1010  */
1011  // having a value type as the argument, rather than reference to const
1012  // and then initialising a tmp object, gives the compiler more scope
1013  // for optimisation, and also caters for r-values without a separate
1014  // overload
1016  std::swap(ref_items, sh_ptr.ref_items);
1017  return *this;
1018  }
1019 
1020  /**
1021  * A version of the assignment operator which enables pointer type
1022  * conversion (assuming the type passed is implicitly type
1023  * convertible to the managed type, such as a derived type). This
1024  * method does not throw unless the destructor of a managed object
1025  * throws.
1026  * @param sh_ptr the assignor.
1027  * @return The SharedLockPtr object after assignment.
1028  */
1029  template <class U> SharedLockPtr& operator=(const SharedLockPtr<U>& sh_ptr) {
1030  return operator=(SharedLockPtr(sh_ptr));
1031  }
1032 
1033  /**
1034  * A version of the operator for move assignment which enables
1035  * pointer type conversion (assuming the type passed is implicitly
1036  * type convertible to the managed type, such as a derived type).
1037  * This method does not throw unless the destructor of a managed
1038  * object throws.
1039  * @param sh_ptr the shared pointer to be moved.
1040  * @return The SharedLockPtr object after the move operation.
1041  */
1042  template <class U> SharedLockPtr& operator=(SharedLockPtr<U>&& sh_ptr) {
1043  return operator=(SharedLockPtr(std::move(sh_ptr)));
1044  }
1045 
1046  /**
1047  * This method does not throw.
1048  * @return A pointer to the managed object (or NULL if none is
1049  * managed).
1050  */
1051  T* get() const {return ref_items.obj_p;}
1052 
1053  /**
1054  * This method does not throw.
1055  * @return A reference to the managed object.
1056  */
1057  T& operator*() const {return *ref_items.obj_p;}
1058 
1059  /**
1060  * This method does not throw.
1061  * @return A pointer to the managed object (or NULL if none is
1062  * managed).
1063  */
1064  T* operator->() const {return ref_items.obj_p;}
1065 
1066  /**
1067  * This method does not throw.
1068  * @return The number of SharedLockPtr objects referencing the
1069  * managed object (or 0 if none is managed by this SharedLockPtr).
1070  * @note The return value may not be valid if another thread has
1071  * changed the reference count before the value returned by this
1072  * method is acted on. It is provided as a utility, but may not be
1073  * meaningful, depending on the intended usage.
1074  */
1075  unsigned int get_refcount() const {
1076  if (!ref_items.ref_count_p) return 0;
1077 #ifdef CGU_SHARED_LOCK_PTR_USE_MUTEX
1078  Thread::Mutex::Lock lock(*ref_items.mutex_p);
1079  return *ref_items.ref_count_p;
1080 #else
1081  return g_atomic_int_get(ref_items.ref_count_p);
1082 #endif
1083  }
1084 
1085  /**
1086  * The destructor does not throw unless the destructor of a managed
1087  * object throws - that should never happen.
1088  */
1089  ~SharedLockPtr() {unreference();}
1090 };
1091 
1092 #if defined(CGU_USE_SMART_PTR_COMPARISON) || defined(DOXYGEN_PARSING)
1093 
1094 // we can use built-in operator == when comparing pointers referencing
1095 // different objects of the same type
1096 /**
1097  * @ingroup handles
1098  *
1099  * This comparison operator does not throw. It compares the addresses
1100  * of the managed objects.
1101  *
1102  * Since 2.0.0-rc2
1103  */
1104 template <class T>
1105 bool operator==(const SharedPtr<T>& s1, const SharedPtr<T>& s2) {
1106  return (s1.get() == s2.get());
1107 }
1108 
1109 /**
1110  * @ingroup handles
1111  *
1112  * This comparison operator does not throw. It compares the addresses
1113  * of the managed objects.
1114  *
1115  * Since 2.0.0-rc2
1116  */
1117 template <class T>
1118 bool operator!=(const SharedPtr<T>& s1, const SharedPtr<T>& s2) {
1119  return !(s1 == s2);
1120 }
1121 
1122 // we must use std::less rather than the < built-in operator for
1123 // pointers to objects not within the same array or object: "For
1124 // templates greater, less, greater_equal, and less_equal, the
1125 // specializations for any pointer type yield a total order, even if
1126 // the built-in operators <, >, <=, >= do not." (para 20.3.3/8).
1127 /**
1128  * @ingroup handles
1129  *
1130  * This comparison operator does not throw. It compares the addresses
1131  * of the managed objects.
1132  *
1133  * Since 2.0.0-rc2
1134  */
1135 template <class T>
1136 bool operator<(const SharedPtr<T>& s1, const SharedPtr<T>& s2) {
1137  return std::less<T*>()(s1.get(), s2.get());
1138 }
1139 
1140 /**
1141  * @ingroup handles
1142  *
1143  * This comparison operator does not throw. It compares the addresses
1144  * of the managed objects.
1145  *
1146  * Since 2.0.0-rc2
1147  */
1148 template <class T>
1149 bool operator==(const SharedLockPtr<T>& s1, const SharedLockPtr<T>& s2) {
1150  return (s1.get() == s2.get());
1151 }
1152 
1153 /**
1154  * @ingroup handles
1155  *
1156  * This comparison operator does not throw. It compares the addresses
1157  * of the managed objects.
1158  *
1159  * Since 2.0.0-rc2
1160  */
1161 template <class T>
1162 bool operator!=(const SharedLockPtr<T>& s1, const SharedLockPtr<T>& s2) {
1163  return !(s1 == s2);
1164 }
1165 
1166 /**
1167  * @ingroup handles
1168  *
1169  * This comparison operator does not throw. It compares the addresses
1170  * of the managed objects.
1171  *
1172  * Since 2.0.0-rc2
1173  */
1174 template <class T>
1175 bool operator<(const SharedLockPtr<T>& s1, const SharedLockPtr<T>& s2) {
1176  return std::less<T*>()(s1.get(), s2.get());
1177 }
1178 
1179 #endif // CGU_USE_SMART_PTR_COMPARISON
1180 
1181 } // namespace Cgu
1182 
1183 // doxygen produces long filenames that tar can't handle:
1184 // we have generic documentation for std::hash specialisations
1185 // in doxygen.main.in
1186 #if defined(CGU_USE_SMART_PTR_COMPARISON) && !defined(DOXYGEN_PARSING)
1187 /* These structs allow SharedPtr and SharedLockPtr objects to be keys
1188  in unordered associative containers */
1189 namespace std {
1190 template <class T>
1191 struct hash<Cgu::SharedPtr<T>> {
1192  typedef std::size_t result_type;
1193  typedef Cgu::SharedPtr<T> argument_type;
1194  result_type operator()(const argument_type& s) const {
1195  // this is fine: std::hash structs do not normally contain data and
1196  // std::hash<T*> certainly won't, so we don't have overhead constructing
1197  // std::hash<T*> on the fly
1198  return std::hash<T*>()(s.get());
1199  }
1200 };
1201 template <class T>
1202 struct hash<Cgu::SharedLockPtr<T>> {
1203  typedef std::size_t result_type;
1204  typedef Cgu::SharedLockPtr<T> argument_type;
1205  result_type operator()(const argument_type& s) const {
1206  // this is fine: std::hash structs do not normally contain data and
1207  // std::hash<T*> certainly won't, so we don't have overhead constructing
1208  // std::hash<T*> on the fly
1209  return std::hash<T*>()(s.get());
1210  }
1211 };
1212 } // namespace std
1213 #endif // CGU_USE_SMART_PTR_COMPARISON
1214 
1215 #endif