cartobase  4.5.0
rcptr.h
Go to the documentation of this file.
1 /* This software and supporting documentation are distributed by
2  * Institut Federatif de Recherche 49
3  * CEA/NeuroSpin, Batiment 145,
4  * 91191 Gif-sur-Yvette cedex
5  * France
6  *
7  * This software is governed by the CeCILL-B license under
8  * French law and abiding by the rules of distribution of free software.
9  * You can use, modify and/or redistribute the software under the
10  * terms of the CeCILL-B license as circulated by CEA, CNRS
11  * and INRIA at the following URL "http://www.cecill.info".
12  *
13  * As a counterpart to the access to the source code and rights to copy,
14  * modify and redistribute granted by the license, users are provided only
15  * with a limited warranty and the software's author, the holder of the
16  * economic rights, and the successive licensors have only limited
17  * liability.
18  *
19  * In this respect, the user's attention is drawn to the risks associated
20  * with loading, using, modifying and/or developing or reproducing the
21  * software by the user in light of its specific status of free software,
22  * that may mean that it is complicated to manipulate, and that also
23  * therefore means that it is reserved for developers and experienced
24  * professionals having in-depth computer knowledge. Users are therefore
25  * encouraged to load and test the software's suitability as regards their
26  * requirements in conditions enabling the security of their systems and/or
27  * data to be ensured and, more generally, to use and operate it in the
28  * same conditions as regards security.
29  *
30  * The fact that you are presently reading this means that you have had
31  * knowledge of the CeCILL-B license and that you accept its terms.
32  */
33 
34 
35 #ifndef CARTOBASE_SMART_RCPTR_H
36 #define CARTOBASE_SMART_RCPTR_H
37 
39 #include <memory>
40 #include <iostream>
41 
42 // uncomment this line to get debugging information
43 // #define DEBUG_REF
44 
45 // comment this line to disable thread-safe code using ZooLib atomic operations
46 #define CARTO_THREADED_RCPTR
47 
48 #ifdef CARTO_THREADED_RCPTR
49 #ifndef CARTO_NO_BOOST
50 #include <boost/version.hpp>
51 #if BOOST_VERSION >= 103300 && \
52  ( !defined( linux ) || ( defined( __GNUC__ ) && __GNUC__ >= 4 ) )
53 #include <boost/detail/atomic_count.hpp>
54 #ifndef BOOST_AC_USE_PTHREADS
55 #define CARTO_RCPTR_USE_BOOST
56 #endif
57 #endif // BOOST_VERSION
58 #endif // CARTO_NO_BOOST
59 
60 #ifndef CARTO_RCPTR_USE_BOOST
61 // try using ZooLib-based implementation
63 #endif
64 
65 #if !defined( CARTO_RCPTR_USE_BOOST ) && !defined( CARTO_RCPTR_USE_ZOOLIB )
66 #undef CARTO_THREADED_RCPTR
67 #endif
68 
69 #endif // CARTO_THREADED_RCPTR
70 
71 namespace carto {
72 
75 template <class T>
76 class const_ref;
77 template <class T>
78 class ref;
79 
80 
83 #ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
84 
89 {
90  template <class T> friend class ref;
91  template <class T> friend class const_ref;
92 
93  template <class T>
94  static void destroy( const_ref<T> * );
95  template <class T>
96  static void construct( const_ref<T> *, const T *, bool externalowner );
97  template <class T>
98  static const T *release( const_ref<T> * );
99 };
100 
101 #endif // DOXYGEN_HIDE_INTERNAL_CLASSES
102 
105 class RCObject
106 #ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
107 : public virtual DefaultRefConstruction
108 #endif // DOXYGEN_HIDE_INTERNAL_CLASSES
109 {
110  template <class T> friend class ref;
111  template <class T> friend class const_ref;
112  template <class T> friend class shared_ptr;
113  friend class rc_ptr_trick;
114 
115  template <class T>
116  static void destroy( const_ref<T> * );
117  template <class T>
118  static void construct( const_ref<T> *, const T *, bool externalowner );
119  template <class T>
120  static const T *release( const_ref<T> * );
121 
122 public:
123 #ifdef CARTO_THREADED_RCPTR
124  typedef boost::detail::atomic_count RefCounterType;
125 #else
126  typedef int RefCounterType;
127 #endif
128 
129 private:
130  mutable RefCounterType _refCounter;
131 
132 public:
133 
134  inline RCObject() : _refCounter( 0 ) {}
135 
136  inline RCObject( const RCObject & )
137  : _refCounter( 0 ) {}
138 
139  inline RCObject & operator = ( const RCObject & ) { return *this; }
140 
141 #ifdef CARTO_DEBUG
142  inline virtual ~RCObject()
143  {
144  long refCounter = _refCounter;
145  if( refCounter > 0 )
146  std::cerr << "RCObject destructor called while " << refCounter
147  << " references are still alive on object " << this
148  << std::endl;
149  }
150 #endif
151 };
152 
153 
154 class rc_ptr_trick;
155 
156 
159 #ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
160 
168 template <class T>
170 {
171  template <class R> friend class ref;
172  template <class R> friend class const_ref;
173 
178  RefConstruction();
179 };
180 
188 template <class T>
189 class RefData
190 {
191  template <class R> friend class const_ref;
192  template <class R> friend class ref;
194  friend class RCObject;
195  friend class rc_ptr_trick;
196 
197  RCObject::RefCounterType *_pcount;
198  T *_ref;
199 
200 public:
201 
202  inline int count() const
203  {
204  return ( _pcount ? *_pcount : 0 );
205  }
206 };
207 #endif // DOXYGEN_HIDE_INTERNAL_CLASSES
208 
209 
212 
280 template <class T>
281 class const_ref
282 #ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
283 : public RefData<T>
284 #endif // DOXYGEN_HIDE_INTERNAL_CLASSES
285 {
286 
287 #ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
289  friend class RCObject;
290 #endif // DOXYGEN_HIDE_INTERNAL_CLASSES
291  template <class R> friend class ref;
292 
293 public:
294 
295  typedef T referenced_type;
296  inline const_ref() { this->_pcount = 0; this->_ref = 0; }
297 
298  inline explicit const_ref( const T *pObject )
299  {
300  RefConstruction<T>::construct( this, pObject, false );
301  }
302 
303  inline explicit const_ref( const T *pObject, bool externalowner )
304  {
305  RefConstruction<T>::construct( this, pObject, externalowner );
306  }
307 
308  inline const_ref( const ref<T> &other ) {
309 #ifdef DEBUG_REF
310  std::cout << "New ref from other ref (" << other._ref << ")" << std::endl;
311 #endif
312  if( other._pcount && *other._pcount >= 0 )
313  ++(*other._pcount);
314  this->_pcount = other._pcount;
315  this->_ref = other._ref;
316  }
317 
318  inline const_ref( const const_ref<T> &other ) {
319 #ifdef DEBUG_REF
320  std::cout << "New ref from other ref (" << other._ref << ")" << std::endl;
321 #endif
322  if( other._pcount && *other._pcount >= 0 )
323  ++(*other._pcount);
324  this->_pcount = other._pcount;
325  this->_ref = other._ref;
326  }
327 
328  template <class R>
329  inline const_ref( const ref<R> &o ){
330  const RefData<R> &other = o;
331 #ifdef DEBUG_REF
332  std::cout << "New ref from other ref with static cast (" << other._ref
333  << ")" << std::endl;
334 #endif
335  if( other._pcount && *other._pcount >= 0 )
336  ++(*other._pcount);
337  this->_pcount = other._pcount;
338  this->_ref = static_cast<T *>( other._ref );
339  }
340 
341  template <class R>
342  inline const_ref( const const_ref<R> &other ){
343 #ifdef DEBUG_REF
344  std::cout << "New ref from other ref with static cast (" << other._ref << ")" << std::endl;
345 #endif
346  if( other._pcount && *other._pcount >= 0 )
347  ++(*other._pcount);
348  this->_pcount = other._pcount;
349  this->_ref = static_cast<T *>( other._ref );
350  }
351 
353 
354  // const_ref<T> &operator =( const T *pObject );
355  const_ref<T> &operator =( const ref<T> &other );
356  const_ref<T> &operator =( const const_ref<T> &other );
357 
358  inline bool isNull() const { return this->_pcount == NULL; }
359  inline bool operator ==( const ref<T> &other ) const { return this->_ref == other._ref; }
360  inline bool operator ==( const T *pointer ) const { return this->_ref == pointer; }
361  inline bool operator ==( const const_ref<T> &other ) const { return this->_ref == other._ref; }
362  inline bool operator !=( const ref<T> &other ) const { return this->_ref != other._ref; }
363  inline bool operator !=( const const_ref<T> &other ) const { return this->_ref != other._ref; }
364  inline bool operator !=( const T *pointer ) const { return this->_ref != pointer; }
365 
366  inline const T *operator ->() const {
367  return static_cast<const T *>( this->_ref );
368  }
369 
370  inline const T &operator *() const {
371  return *static_cast<const T *>( this->_ref );
372  }
373 
374  inline const T *pointer() const {
375  return static_cast<const T *>( this->_ref );
376  }
377 
378  inline int refCount() const
379  {
380  return this->_pcount ? *this->_pcount : 0;
381  }
382 };
383 
384 
386  /*
387 template <class T>
388 const_ref<T> &const_ref<T>::operator =( const T *pObject ) {
389 #ifdef DEBUG_REF
390  std::cout << "ref (" << this->_ref << ") = " << pObject << std::endl;
391 #endif
392  if ( this->_ref != pObject ) {
393  RefConstruction<T>::destroy( this );
394  RefConstruction<T>::construct( this, pObject, false );
395  }
396  return *this;
397 }
398  */
399 
401 template <class T>
403 #ifdef DEBUG_REF
404  std::cout << "ref (" << this->_ref << ") = ref (" << other._ref << ")"
405  << std::endl;
406 #endif
407  if ( this->_ref != other._ref )
408  {
409  if( other._pcount && *other._pcount >= 0 )
410  ++(*other._pcount);
412  this->_pcount = other._pcount;
413  this->_ref = other._ref;
414  }
415  return *this;
416 }
417 
419 template <class T>
421 #ifdef DEBUG_REF
422  std::cout << "ref (" << this->_ref << ") = ref (" << other._ref << ")"
423  << std::endl;
424 #endif
425  if ( this != &other && this->_ref != other._ref )
426  {
427  if( other._pcount && *other._pcount >= 0 )
428  ++(*other._pcount);
430  this->_pcount = other._pcount;
431  this->_ref = other._ref;
432  }
433  return *this;
434 }
435 
436 
440 template <class T>
441 class ref : public const_ref<T>
442 {
443  template <class R> friend class const_ref;
444 
445 public:
446 
447  typedef T referenced_type;
448 
449  inline ref() : const_ref<T>() {
450 #ifdef DEBUG_REF
451  std::cout << "New empty ref" << std::endl;
452 #endif
453  }
454 
455  inline explicit ref( T *pObject ) : const_ref<T>( pObject ) {}
456  inline explicit ref( T *pObject, bool externalowner )
457  : const_ref<T>( pObject, externalowner ) {}
458 
459  inline ref( const ref<T> &other ) : const_ref<T>( other ) {}
460 
461  template <class R>
462  inline ref( const ref<R> &other ) : const_ref<T>( other ) {}
463 
464  inline ~ref() {}
465 
466  inline T *release() {
467  return const_cast<T *>( RefConstruction<T>::release( this ) );
468  }
469 
470  inline ref<T> &operator =( const ref<T> &other ) {
471  this->const_ref<T>::operator =( other );
472  return *this;
473  }
474 
475  inline T *operator ->() const {
476  return static_cast<T *>( this->_ref );
477  }
478 
479  inline T &operator *() const {
480  return *static_cast<T *>( this->_ref );
481  }
482 
483  inline T *pointer() const {
484  return static_cast<T *>( this->_ref );
485  }
486 
487 };
488 
489 
490 
492 #ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
493 template <class T>
494 void DefaultRefConstruction::construct( const_ref<T> *r, const T *pObject,
495  bool externalowner )
496 {
497 #ifdef DEBUG_REF
498  std::cout << "New ref (" << pObject << ")" << std::endl;
499 #endif
500  if ( pObject && !externalowner )
501  r->_pcount = new RCObject::RefCounterType( 1 );
502  else r->_pcount = NULL;
503  r->_ref = const_cast<T *>( pObject );
504 }
505 
507 template <class T>
508 void DefaultRefConstruction::destroy( const_ref<T> *r ) {
509 #ifdef DEBUG_REF
510  std::cout << "Deleting ref (" << r->_ref << ")" << std::endl;
511 #endif
512  if ( r->_pcount && --(*r->_pcount) == 0 )
513  {
514 #ifdef DEBUG_REF
515  std::cout << "Deleting ref object (" << r->_ref << ")" << std::endl;
516 #endif
517  delete r->_pcount;
518  delete static_cast<T *>( r->_ref );
519  }
520 }
521 
523 template <class T>
524 const T *DefaultRefConstruction::release( const_ref<T> *r ) {
525 #ifdef DEBUG_REF
526  std::cout << "Releasing ref (" << r->_ref << ")" << std::endl;
527 #endif
528  const T * const result = r->_ref;
529  if ( r->_pcount && --(*r->_pcount) == 0 )
530  {
531  delete r->_pcount;
532  r->_pcount = 0;
533  }
534  r->_ref = NULL;
535  return result;
536 }
537 #endif // DOXYGEN_HIDE_INTERNAL_CLASSES
538 
541 
542 
543 
544 
546 template <class T>
547 void RCObject::construct( const_ref<T> *r, const T * pObject,
548  bool externalowner )
549 {
550 #ifdef DEBUG_REF
551  std::cout << "New RCObject (" << pObject << ")" << std::endl;
552 #endif
553  if( pObject )
554  {
555  long x = pObject->_refCounter;
556  if( externalowner && x == 0 )
557  {
558  --pObject->_refCounter;
559  // r->_pcount = NULL;
560  }
561  else if( x >= 0 )
562  ++pObject->_refCounter;
563  r->_pcount = &pObject->_refCounter;
564  }
565  else
566  r->_pcount = NULL;
567  r->_ref = const_cast<T *>( pObject );
568 }
569 
571 template <class T>
572 void RCObject::destroy( const_ref<T> *r )
573 {
574 #ifdef DEBUG_REF
575  std::cout << "RCObject::destroy (" << r->_ref << ")" << std::endl;
576  if( r->_pcount )
577  std::cout << " count: " << *r->_pcount << std::endl;
578  else
579  std::cout << " no counter\n";
580 #endif
581  if( r->_pcount && --(*r->_pcount) == 0 )
582  {
583 #ifdef DEBUG_REF
584  std::cout << "Deleting RCObject object (" << r->_ref << ")" << std::endl;
585 #endif
586  delete static_cast<T *>( r->_ref );
587  }
588 }
589 
591 template <class T>
592 const T *RCObject::release( const_ref<T> *r ) {
593 #ifdef DEBUG_REF
594  std::cout << "Releasing RCObject (" << r->_ref << ")" << std::endl;
595 #endif
596  const T * const result = r->_ref;
597  if ( r->_pcount && *r->_pcount >= 0 )
598  --(*r->_pcount);
599  r->_pcount = 0;
600  r->_ref = 0;
601  return result;
602 }
603 
604 
605 template <typename T>
606 class rc_ptr : public ref<T>
607 {
608 public:
609 #ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
610  class insipid
611  {
612  protected:
613  void operator delete( void* );
614  void operator delete[]( void* );
615  };
616 #endif
617 
618  inline rc_ptr() {}
619  inline explicit rc_ptr( T *p ) : ref<T>( p ) {}
620  inline explicit rc_ptr( T *p, bool externalowner )
621  : ref<T>( p, externalowner ) {}
622 
623  inline void reset( T *p = NULL )
624  { *static_cast< ref<T> * >( this ) = ref<T>( p ); }
625  inline T *get() const { return this->pointer(); }
626  inline bool operator <( const rc_ptr<T> &other ) const {
627  return this->pointer() < other.pointer();
628  }
629 
630 #ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
631  inline operator insipid*() const
632  {
633  return reinterpret_cast< insipid* >( this->pointer() );
634  }
635 #endif
636 };
637 
638 
639 
640 template <>
642 {
643 
644  private:
645 
646  template < class R > friend class ref;
647  template < class R > friend class const_ref;
648 
649  RefConstruction();
650 
651 
652 };
653 
654 
655 template <>
656 class RefConstruction< unsigned char > : DefaultRefConstruction
657 {
658 
659  private:
660 
661  template < class R > friend class ref;
662  template < class R > friend class const_ref;
663 
664  RefConstruction();
665 
666 
667 };
668 
669 
670 template <>
672 {
673 
674  private:
675 
676  template < class R > friend class ref;
677  template < class R > friend class const_ref;
678 
679  RefConstruction();
680 
681 
682 };
683 
684 
685 template <>
686 class RefConstruction< unsigned short > : DefaultRefConstruction
687 {
688 
689  private:
690 
691  template < class R > friend class ref;
692  template < class R > friend class const_ref;
693 
694  RefConstruction();
695 
696 
697 };
698 
699 
700 template <>
702 {
703 
704  private:
705 
706  template < class R > friend class ref;
707  template < class R > friend class const_ref;
708 
709  RefConstruction();
710 
711 
712 };
713 
714 
715 template <>
717 {
718 
719  private:
720 
721  template < class R > friend class ref;
722  template < class R > friend class const_ref;
723 
724  RefConstruction();
725 
726 
727 };
728 
729 
730 template <>
732 {
733 
734  private:
735 
736  template < class R > friend class ref;
737  template < class R > friend class const_ref;
738 
739  RefConstruction();
740 
741 
742 };
743 
744 
745 template <>
746 class RefConstruction< unsigned long > : DefaultRefConstruction
747 {
748 
749  private:
750 
751  template < class R > friend class ref;
752  template < class R > friend class const_ref;
753 
754  RefConstruction();
755 
756 
757 };
758 
759 
760 template <>
762 {
763 
764  private:
765 
766  template < class R > friend class ref;
767  template < class R > friend class const_ref;
768 
769  RefConstruction();
770 
771 
772 };
773 
774 
775 template <>
777 {
778 
779  private:
780 
781  template < class R > friend class ref;
782  template < class R > friend class const_ref;
783 
784  RefConstruction();
785 
786 
787 };
788 
789 
790 } // namespace carto
791 
792 
793 #endif
T * pointer() const
Definition: rcptr.h:483
bool operator!=(const ref< T > &other) const
Definition: rcptr.h:362
RCObject(const RCObject &)
Definition: rcptr.h:136
Constant Ref to an object of class T.
Definition: rcptr.h:76
~ref()
Definition: rcptr.h:464
const_ref(const ref< T > &other)
Definition: rcptr.h:308
int count() const
Definition: rcptr.h:202
const_ref< T > & operator=(const ref< T > &other)
Definition: rcptr.h:402
A multi-purpose general smart pointer, which can act as either a rc_ptr, a weak_ptr or a weak_shared_...
Definition: sharedptr.h:144
ref< T > & operator=(const ref< T > &other)
Definition: rcptr.h:470
ref(T *pObject, bool externalowner)
Definition: rcptr.h:456
T * release()
Definition: rcptr.h:466
T referenced_type
Definition: rcptr.h:447
bool isNull() const
Definition: rcptr.h:358
Base class for reference counted objects (intrusive)
Definition: rcptr.h:105
const_ref(const T *pObject)
Definition: rcptr.h:298
ref(const ref< T > &other)
Definition: rcptr.h:459
RCObject & operator=(const RCObject &)
Definition: rcptr.h:139
bool operator==(const ref< T > &other) const
Definition: rcptr.h:359
int RefCounterType
Definition: rcptr.h:126
const T * pointer() const
Definition: rcptr.h:374
int refCount() const
Definition: rcptr.h:378
Reference-counting pointer.
Definition: rcptr.h:606
const_ref(const const_ref< R > &other)
Definition: rcptr.h:342
rc_ptr_trick merely makes a public access to the reference counter inside a rc_ptr.
Definition: rcptrtrick.h:49
const T * operator->() const
Definition: rcptr.h:366
A ref is a const_ref which can reference non constant objects.
Definition: rcptr.h:78
const T & operator*() const
Definition: rcptr.h:370
rc_ptr(T *p)
Definition: rcptr.h:619
rc_ptr(T *p, bool externalowner)
Definition: rcptr.h:620
T & operator*() const
Definition: rcptr.h:479
ref(const ref< R > &other)
Definition: rcptr.h:462
const_ref(const T *pObject, bool externalowner)
Definition: rcptr.h:303
const_ref(const ref< R > &o)
Definition: rcptr.h:329
void reset(T *p=NULL)
Definition: rcptr.h:623
ref(T *pObject)
Definition: rcptr.h:455
const_ref(const const_ref< T > &other)
Definition: rcptr.h:318
T * operator->() const
Definition: rcptr.h:475