cartobase  5.0.5
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 #include <utility>
42 
43 // uncomment this line to get debugging information
44 // #define DEBUG_REF
45 
46 // comment this line to disable thread-safe code using ZooLib atomic operations
47 #define CARTO_THREADED_RCPTR
48 
49 #ifdef CARTO_THREADED_RCPTR
50 #ifndef CARTO_NO_BOOST
51 #include <boost/version.hpp>
52 #if BOOST_VERSION >= 103300 && \
53  ( !defined( linux ) || ( defined( __GNUC__ ) && __GNUC__ >= 4 ) )
54 #include <boost/detail/atomic_count.hpp>
55 #ifndef BOOST_AC_USE_PTHREADS
56 #define CARTO_RCPTR_USE_BOOST
57 #endif
58 #endif // BOOST_VERSION
59 #endif // CARTO_NO_BOOST
60 
61 #ifndef CARTO_RCPTR_USE_BOOST
62 // try using ZooLib-based implementation
64 #endif
65 
66 #if !defined( CARTO_RCPTR_USE_BOOST ) && !defined( CARTO_RCPTR_USE_ZOOLIB )
67 #undef CARTO_THREADED_RCPTR
68 #endif
69 
70 #endif // CARTO_THREADED_RCPTR
71 
72 namespace carto {
73 
76 template <class T>
77 class const_ref;
78 template <class T>
79 class ref;
80 
81 
84 #ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
85 
90 {
91  template <class T> friend class ref;
92  template <class T> friend class const_ref;
93 
94  template <class T>
95  static void destroy( const_ref<T> * );
96  template <class T>
97  static void construct( const_ref<T> *, const T *, bool externalowner );
98  template <class T>
99  static const T *release( const_ref<T> * );
100 };
101 
102 #endif // DOXYGEN_HIDE_INTERNAL_CLASSES
103 
106 class RCObject
107 #ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
108 : public virtual DefaultRefConstruction
109 #endif // DOXYGEN_HIDE_INTERNAL_CLASSES
110 {
111  template <class T> friend class ref;
112  template <class T> friend class const_ref;
113  template <class T> friend class shared_ptr;
114  friend class rc_ptr_trick;
115 
116  template <class T>
117  static void destroy( const_ref<T> * );
118  template <class T>
119  static void construct( const_ref<T> *, const T *, bool externalowner );
120  template <class T>
121  static const T *release( const_ref<T> * );
122 
123 public:
124 #ifdef CARTO_THREADED_RCPTR
125  typedef boost::detail::atomic_count RefCounterType;
126 #else
127  typedef int RefCounterType;
128 #endif
129 
130 private:
131  mutable RefCounterType _refCounter;
132 
133 public:
134 
135  inline RCObject() : _refCounter( 0 ) {}
136 
137  inline RCObject( const RCObject & )
138  : _refCounter( 0 ) {}
139 
140  inline RCObject & operator = ( const RCObject & ) { return *this; }
141 
142  inline virtual ~RCObject()
143  {
144  // set counter to 0 in case of forced deletion
145  long refCounter = _refCounter;
146 #ifdef CARTO_DEBUG
147  if( refCounter > 0 )
148  std::cerr << "RCObject destructor called while " << refCounter
149  << " references are still alive on object " << this
150  << std::endl;
151 #endif
152  if( refCounter > 0 )
153  for( long i=0; i<refCounter; ++i )
154  --_refCounter;
155  else
156  for( long i=0; i<-refCounter; ++i )
157  ++_refCounter;
158  }
159 };
160 
161 
162 class rc_ptr_trick;
163 
164 
167 #ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
168 
176 template <class T>
178 {
179  template <class R> friend class ref;
180  template <class R> friend class const_ref;
181 
186  RefConstruction();
187 };
188 
196 template <class T>
197 class RefData
198 {
199  template <class R> friend class const_ref;
200  template <class R> friend class ref;
202  friend class RCObject;
203  friend class rc_ptr_trick;
204 
205  RCObject::RefCounterType *_pcount;
206  T *_ref;
207 
208 public:
209 
210  inline int count() const
211  {
212  return ( _pcount ? *_pcount : 0 );
213  }
214 };
215 #endif // DOXYGEN_HIDE_INTERNAL_CLASSES
216 
217 
220 
288 template <class T>
289 class const_ref
290 #ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
291 : public RefData<T>
292 #endif // DOXYGEN_HIDE_INTERNAL_CLASSES
293 {
294 
295 #ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
297  friend class RCObject;
298 #endif // DOXYGEN_HIDE_INTERNAL_CLASSES
299  template <class R> friend class ref;
300 
301 public:
302 
303  typedef T referenced_type;
304  inline const_ref() { this->_pcount = 0; this->_ref = 0; }
305 
306  inline explicit const_ref( const T *pObject )
307  {
308  RefConstruction<T>::construct( this, pObject, false );
309  }
310 
311  inline explicit const_ref( const T *pObject, bool externalowner )
312  {
313  RefConstruction<T>::construct( this, pObject, externalowner );
314  }
315 
316 #if __cplusplus >= 201103L
317  // Only unique_ptr with the default deleter can be converted, because
318  // const_ref does not support custom deleters (it calls the delete operator
319  // upon destruction, just like std::default_delete).
320  template< class U >
321  const_ref( std::unique_ptr<U>&& r )
322  {
323  RefConstruction<T>::construct( this, r.release(), false );
324  }
325 #else
326  template< class U >
327  const_ref( std::auto_ptr<U> r )
328  {
329  RefConstruction<T>::construct( this, r.release(), false );
330  }
331 #endif
332 
333  inline const_ref( const ref<T> &other ) {
334 #ifdef DEBUG_REF
335  std::cout << "New ref from other ref (" << other._ref << ")" << std::endl;
336 #endif
337  if( other._pcount && *other._pcount >= 0 )
338  ++(*other._pcount);
339  this->_pcount = other._pcount;
340  this->_ref = other._ref;
341  }
342 
343  inline const_ref( const const_ref<T> &other ) {
344 #ifdef DEBUG_REF
345  std::cout << "New ref from other ref (" << other._ref << ")" << std::endl;
346 #endif
347  if( other._pcount && *other._pcount >= 0 )
348  ++(*other._pcount);
349  this->_pcount = other._pcount;
350  this->_ref = other._ref;
351  }
352 
353  template <class R>
354  inline const_ref( const ref<R> &o ){
355  const RefData<R> &other = o;
356 #ifdef DEBUG_REF
357  std::cout << "New ref from other ref with implicit cast (" << other._ref
358  << ")" << std::endl;
359 #endif
360  if( other._pcount && *other._pcount >= 0 )
361  ++(*other._pcount);
362  this->_pcount = other._pcount;
363  this->_ref = other._ref;
364  }
365 
366  template <class R>
367  inline const_ref( const const_ref<R> &other ){
368 #ifdef DEBUG_REF
369  std::cout << "New ref from other ref with implicit cast (" << other._ref << ")" << std::endl;
370 #endif
371  if( other._pcount && *other._pcount >= 0 )
372  ++(*other._pcount);
373  this->_pcount = other._pcount;
374  this->_ref = other._ref;
375  }
376 
378 
379  // const_ref<T> &operator =( const T *pObject );
380  const_ref<T> &operator =( const ref<T> &other );
381  const_ref<T> &operator =( const const_ref<T> &other );
382 
383  inline bool isNull() const { return this->_pcount == NULL; }
384  inline bool operator ==( const ref<T> &other ) const { return this->_ref == other._ref; }
385  inline bool operator ==( const T *pointer ) const { return this->_ref == pointer; }
386  inline bool operator ==( const const_ref<T> &other ) const { return this->_ref == other._ref; }
387  inline bool operator !=( const ref<T> &other ) const { return this->_ref != other._ref; }
388  inline bool operator !=( const const_ref<T> &other ) const { return this->_ref != other._ref; }
389  inline bool operator !=( const T *pointer ) const { return this->_ref != pointer; }
390 
391  inline const T *operator ->() const {
392  return static_cast<const T *>( this->_ref );
393  }
394 
395  inline const T &operator *() const {
396  return *static_cast<const T *>( this->_ref );
397  }
398 
399  inline const T *pointer() const {
400  return static_cast<const T *>( this->_ref );
401  }
402 
403  inline int refCount() const
404  {
405  return this->_pcount ? *this->_pcount : 0;
406  }
407 };
408 
409 
411  /*
412 template <class T>
413 const_ref<T> &const_ref<T>::operator =( const T *pObject ) {
414 #ifdef DEBUG_REF
415  std::cout << "ref (" << this->_ref << ") = " << pObject << std::endl;
416 #endif
417  if ( this->_ref != pObject ) {
418  RefConstruction<T>::destroy( this );
419  RefConstruction<T>::construct( this, pObject, false );
420  }
421  return *this;
422 }
423  */
424 
426 template <class T>
428 #ifdef DEBUG_REF
429  std::cout << "ref (" << this->_ref << ") = ref (" << other._ref << ")"
430  << std::endl;
431 #endif
432  if ( this->_ref != other._ref )
433  {
434  if( other._pcount && *other._pcount >= 0 )
435  ++(*other._pcount);
437  this->_pcount = other._pcount;
438  this->_ref = other._ref;
439  }
440  return *this;
441 }
442 
444 template <class T>
446 #ifdef DEBUG_REF
447  std::cout << "ref (" << this->_ref << ") = ref (" << other._ref << ")"
448  << std::endl;
449 #endif
450  if ( this != &other && this->_ref != other._ref )
451  {
452  if( other._pcount && *other._pcount >= 0 )
453  ++(*other._pcount);
455  this->_pcount = other._pcount;
456  this->_ref = other._ref;
457  }
458  return *this;
459 }
460 
461 
465 template <class T>
466 class ref : public const_ref<T>
467 {
468  template <class R> friend class const_ref;
469 
470 public:
471 
472  typedef T referenced_type;
473 
474  inline ref() : const_ref<T>() {
475 #ifdef DEBUG_REF
476  std::cout << "New empty ref" << std::endl;
477 #endif
478  }
479 
480  inline explicit ref( T *pObject ) : const_ref<T>( pObject ) {}
481  inline explicit ref( T *pObject, bool externalowner )
482  : const_ref<T>( pObject, externalowner ) {}
483 
484 #if __cplusplus >= 201103L
485  template< class U >
486  ref( std::unique_ptr<U>&& r ) : const_ref<T>( std::move(r) ) {}
487 #else
488  template< class U >
489  ref( std::auto_ptr<U> r ) : const_ref<T>( r ) {}
490 #endif
491 
492  inline ref( const ref<T> &other ) : const_ref<T>( other ) {}
493 
494  template <class R>
495  inline ref( const ref<R> &other ) : const_ref<T>( other ) {}
496 
497  inline ~ref() {}
498 
499  inline T *release() {
500  return const_cast<T *>( RefConstruction<T>::release( this ) );
501  }
502 
503  inline ref<T> &operator =( const ref<T> &other ) {
504  this->const_ref<T>::operator =( other );
505  return *this;
506  }
507 
508  inline T *operator ->() const {
509  return static_cast<T *>( this->_ref );
510  }
511 
512  inline T &operator *() const {
513  return *static_cast<T *>( this->_ref );
514  }
515 
516  inline T *pointer() const {
517  return static_cast<T *>( this->_ref );
518  }
519 
520 };
521 
522 
523 
525 #ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
526 template <class T>
527 void DefaultRefConstruction::construct( const_ref<T> *r, const T *pObject,
528  bool externalowner )
529 {
530 #ifdef DEBUG_REF
531  std::cout << "New ref (" << pObject << ")" << std::endl;
532 #endif
533  if ( pObject && !externalowner )
534  r->_pcount = new RCObject::RefCounterType( 1 );
535  else r->_pcount = NULL;
536  r->_ref = const_cast<T *>( pObject );
537 }
538 
540 template <class T>
541 void DefaultRefConstruction::destroy( const_ref<T> *r ) {
542 #ifdef DEBUG_REF
543  std::cout << "Deleting ref (" << r->_ref << ")" << std::endl;
544 #endif
545  if ( r->_pcount && --(*r->_pcount) == 0 )
546  {
547 #ifdef DEBUG_REF
548  std::cout << "Deleting ref object (" << r->_ref << ")" << std::endl;
549 #endif
550  delete r->_pcount;
551  delete static_cast<T *>( r->_ref );
552  }
553 }
554 
556 template <class T>
557 const T *DefaultRefConstruction::release( const_ref<T> *r ) {
558 #ifdef DEBUG_REF
559  std::cout << "Releasing ref (" << r->_ref << ")" << std::endl;
560 #endif
561  const T * const result = r->_ref;
562  if ( r->_pcount && --(*r->_pcount) == 0 )
563  {
564  delete r->_pcount;
565  r->_pcount = 0;
566  }
567  r->_ref = NULL;
568  return result;
569 }
570 #endif // DOXYGEN_HIDE_INTERNAL_CLASSES
571 
574 
575 
576 
577 
579 template <class T>
580 void RCObject::construct( const_ref<T> *r, const T * pObject,
581  bool externalowner )
582 {
583 #ifdef DEBUG_REF
584  std::cout << "New RCObject (" << pObject << ")" << std::endl;
585 #endif
586  if( pObject )
587  {
588  long x = pObject->_refCounter;
589  if( externalowner && x == 0 )
590  {
591  --pObject->_refCounter;
592  // r->_pcount = NULL;
593  }
594  else if( x >= 0 )
595  ++pObject->_refCounter;
596  r->_pcount = &pObject->_refCounter;
597  }
598  else
599  r->_pcount = NULL;
600  r->_ref = const_cast<T *>( pObject );
601 }
602 
604 template <class T>
605 void RCObject::destroy( const_ref<T> *r )
606 {
607 #ifdef DEBUG_REF
608  std::cout << "RCObject::destroy (" << r->_ref << ")" << std::endl;
609  if( r->_pcount )
610  std::cout << " count: " << *r->_pcount << std::endl;
611  else
612  std::cout << " no counter\n";
613 #endif
614  if( r->_pcount && --(*r->_pcount) == 0 )
615  {
616 #ifdef DEBUG_REF
617  std::cout << "Deleting RCObject object (" << r->_ref << ")" << std::endl;
618 #endif
619  delete static_cast<T *>( r->_ref );
620  }
621 }
622 
624 template <class T>
625 const T *RCObject::release( const_ref<T> *r ) {
626 #ifdef DEBUG_REF
627  std::cout << "Releasing RCObject (" << r->_ref << ")" << std::endl;
628 #endif
629  const T * const result = r->_ref;
630  if ( r->_pcount && *r->_pcount >= 0 )
631  --(*r->_pcount);
632  r->_pcount = 0;
633  r->_ref = 0;
634  return result;
635 }
636 
637 
638 template <typename T>
639 class rc_ptr : public ref<T>
640 {
641 public:
642 #ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
643  class insipid
644  {
645  protected:
646  void operator delete( void* );
647  void operator delete[]( void* );
648  };
649 #endif
650 
651  inline rc_ptr() {}
652  inline explicit rc_ptr( T *p ) : ref<T>( p ) {}
653  inline explicit rc_ptr( T *p, bool externalowner )
654  : ref<T>( p, externalowner ) {}
655 
656 #if __cplusplus >= 201103L
657  template< class U >
658  rc_ptr( std::unique_ptr<U>&& r ) : ref<T>( std::move(r) ) {}
659 #else
660  template< class U >
661  rc_ptr( std::auto_ptr<U> r ) : ref<T>( r ) {}
662 #endif
663 
664  inline void reset( T *p = NULL )
665  { *static_cast< ref<T> * >( this ) = ref<T>( p ); }
666  inline T *get() const { return this->pointer(); }
667  inline bool operator <( const rc_ptr<T> &other ) const {
668  return this->pointer() < other.pointer();
669  }
670 
671 #ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
672  inline operator insipid*() const
673  {
674  return reinterpret_cast< insipid* >( this->pointer() );
675  }
676 #endif
677 };
678 
679 
680 
681 template <>
683 {
684 
685  private:
686 
687  template < class R > friend class ref;
688  template < class R > friend class const_ref;
689 
690  RefConstruction();
691 
692 
693 };
694 
695 
696 template <>
697 class RefConstruction< unsigned char > : DefaultRefConstruction
698 {
699 
700  private:
701 
702  template < class R > friend class ref;
703  template < class R > friend class const_ref;
704 
705  RefConstruction();
706 
707 
708 };
709 
710 
711 template <>
713 {
714 
715  private:
716 
717  template < class R > friend class ref;
718  template < class R > friend class const_ref;
719 
720  RefConstruction();
721 
722 
723 };
724 
725 
726 template <>
727 class RefConstruction< unsigned short > : DefaultRefConstruction
728 {
729 
730  private:
731 
732  template < class R > friend class ref;
733  template < class R > friend class const_ref;
734 
735  RefConstruction();
736 
737 
738 };
739 
740 
741 template <>
743 {
744 
745  private:
746 
747  template < class R > friend class ref;
748  template < class R > friend class const_ref;
749 
750  RefConstruction();
751 
752 
753 };
754 
755 
756 template <>
758 {
759 
760  private:
761 
762  template < class R > friend class ref;
763  template < class R > friend class const_ref;
764 
765  RefConstruction();
766 
767 
768 };
769 
770 
771 template <>
773 {
774 
775  private:
776 
777  template < class R > friend class ref;
778  template < class R > friend class const_ref;
779 
780  RefConstruction();
781 
782 
783 };
784 
785 
786 template <>
787 class RefConstruction< unsigned long > : DefaultRefConstruction
788 {
789 
790  private:
791 
792  template < class R > friend class ref;
793  template < class R > friend class const_ref;
794 
795  RefConstruction();
796 
797 
798 };
799 
800 
801 template <>
803 {
804 
805  private:
806 
807  template < class R > friend class ref;
808  template < class R > friend class const_ref;
809 
810  RefConstruction();
811 
812 
813 };
814 
815 
816 template <>
818 {
819 
820  private:
821 
822  template < class R > friend class ref;
823  template < class R > friend class const_ref;
824 
825  RefConstruction();
826 
827 
828 };
829 
830 
831 } // namespace carto
832 
833 
834 #endif
RCObject(const RCObject &)
Definition: rcptr.h:137
Constant Ref to an object of class T.
Definition: rcptr.h:77
~ref()
Definition: rcptr.h:497
const_ref(const ref< T > &other)
Definition: rcptr.h:333
const_ref< T > & operator=(const ref< T > &other)
Definition: rcptr.h:427
A multi-purpose general smart pointer, which can act as either a rc_ptr, a weak_ptr or a weak_shared_...
Definition: sharedptr.h:152
ref(T *pObject, bool externalowner)
Definition: rcptr.h:481
T * release()
Definition: rcptr.h:499
ref(std::auto_ptr< U > r)
Definition: rcptr.h:489
T referenced_type
Definition: rcptr.h:472
Base class for reference counted objects (intrusive)
Definition: rcptr.h:106
const_ref(const T *pObject)
Definition: rcptr.h:306
ref(const ref< T > &other)
Definition: rcptr.h:492
int RefCounterType
Definition: rcptr.h:127
const T * pointer() const
Definition: rcptr.h:399
bool operator==(const carto::block< T, N > &b1, const carto::block< T, N > &b2)
Definition: block.h:252
bool isNull() const
Definition: rcptr.h:383
rc_ptr(std::auto_ptr< U > r)
Definition: rcptr.h:661
VoxelRGB operator*(const VoxelRGB &aa, const uint8_t &bb)
Definition: voxelrgb_def.h:637
Reference-counting pointer.
Definition: rcptr.h:639
const_ref(const const_ref< R > &other)
Definition: rcptr.h:367
T * pointer() const
Definition: rcptr.h:516
rc_ptr_trick merely makes a public access to the reference counter inside a rc_ptr.
Definition: rcptrtrick.h:49
int count() const
Definition: rcptr.h:210
A ref is a const_ref which can reference non constant objects.
Definition: rcptr.h:79
rc_ptr(T *p)
Definition: rcptr.h:652
rc_ptr(T *p, bool externalowner)
Definition: rcptr.h:653
ref(const ref< R > &other)
Definition: rcptr.h:495
const_ref(const T *pObject, bool externalowner)
Definition: rcptr.h:311
virtual ~RCObject()
Definition: rcptr.h:142
const_ref(std::auto_ptr< U > r)
Definition: rcptr.h:327
const_ref(const ref< R > &o)
Definition: rcptr.h:354
int refCount() const
Definition: rcptr.h:403
friend class const_ref
Definition: rcptr.h:92
void reset(T *p=NULL)
Definition: rcptr.h:664
ref(T *pObject)
Definition: rcptr.h:480
const_ref(const const_ref< T > &other)
Definition: rcptr.h:343