cartobase 6.0.6
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
72namespace carto {
73
76template <class T>
77class const_ref;
78template <class T>
79class ref;
80
81
84#ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
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
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
123public:
124#ifdef CARTO_THREADED_RCPTR
125 typedef boost::detail::atomic_count RefCounterType;
126#else
127 typedef int RefCounterType;
128#endif
129
130private:
131 mutable RefCounterType _refCounter;
132
133public:
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
162class rc_ptr_trick;
163
164
167#ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
176template <class T>
177class RefConstruction : T, virtual DefaultRefConstruction
178{
179 template <class R> friend class ref;
180 template <class R> friend class const_ref;
181
186 RefConstruction();
187};
188
196template <class T>
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
206 T *_ref;
207
208public:
209
210 inline int count() const
211 {
212 return ( _pcount ? *_pcount : 0 );
213 }
214};
215#endif // DOXYGEN_HIDE_INTERNAL_CLASSES
216
217
220
288template <class T>
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
301public:
302
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
377 inline ~const_ref() { RefConstruction<T>::destroy( this ); }
378
379 // const_ref<T> &operator =( const T *pObject );
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 /*
412template <class T>
413const_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
426template <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);
436 RefConstruction<T>::destroy( this );
437 this->_pcount = other._pcount;
438 this->_ref = other._ref;
439 }
440 return *this;
441}
442
444template <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);
454 RefConstruction<T>::destroy( this );
455 this->_pcount = other._pcount;
456 this->_ref = other._ref;
457 }
458 return *this;
459}
460
461
465template <class T>
466class ref : public const_ref<T>
467{
468 template <class R> friend class const_ref;
469
470public:
471
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
526template <class T>
527void 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
540template <class T>
541void 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
556template <class T>
557const 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
579template <class T>
580void 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
604template <class T>
605void 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
624template <class T>
625const 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
638template <typename T>
639class rc_ptr : public ref<T>
640{
641public:
642#ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
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
681template <>
682class RefConstruction< char > : DefaultRefConstruction
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
696template <>
697class 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
711template <>
712class RefConstruction< short > : DefaultRefConstruction
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
726template <>
727class 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
741template <>
742class RefConstruction< int > : DefaultRefConstruction
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
756template <>
757class RefConstruction< unsigned int > : DefaultRefConstruction
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
771template <>
772class RefConstruction< long > : DefaultRefConstruction
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
786template <>
787class 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
801template <>
802class RefConstruction< float > : DefaultRefConstruction
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
816template <>
817class RefConstruction< double > : DefaultRefConstruction
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
RCObject & operator=(const RCObject &)
Definition rcptr.h:140
virtual ~RCObject()
Definition rcptr.h:142
friend class ref
Definition rcptr.h:111
friend class shared_ptr
Definition rcptr.h:113
int RefCounterType
Definition rcptr.h:127
friend class rc_ptr_trick
Definition rcptr.h:114
friend class const_ref
Definition rcptr.h:112
friend class ref
Definition rcptr.h:179
friend class const_ref
Definition rcptr.h:180
int count() const
Definition rcptr.h:210
friend class DefaultRefConstruction
Definition rcptr.h:201
friend class ref
Definition rcptr.h:200
friend class RCObject
Definition rcptr.h:202
friend class rc_ptr_trick
Definition rcptr.h:203
friend class const_ref
Definition rcptr.h:199
Constant Ref to an object of class T.
Definition rcptr.h:293
const_ref(const ref< T > &other)
Definition rcptr.h:333
bool operator!=(const ref< T > &other) const
Definition rcptr.h:387
const T * pointer() const
Definition rcptr.h:399
const_ref(const const_ref< R > &other)
Definition rcptr.h:367
const_ref(const T *pObject)
Definition rcptr.h:306
const_ref(std::auto_ptr< U > r)
Definition rcptr.h:327
friend class DefaultRefConstruction
Definition rcptr.h:296
const_ref(const ref< R > &o)
Definition rcptr.h:354
const_ref(const const_ref< T > &other)
Definition rcptr.h:343
bool operator==(const ref< T > &other) const
Definition rcptr.h:384
const_ref< T > & operator=(const ref< T > &other)
Definition rcptr.h:427
const T * operator->() const
Definition rcptr.h:391
friend class ref
Definition rcptr.h:299
friend class RCObject
Definition rcptr.h:297
bool isNull() const
Definition rcptr.h:383
const T & operator*() const
Definition rcptr.h:395
const_ref(const T *pObject, bool externalowner)
Definition rcptr.h:311
int refCount() const
Definition rcptr.h:403
bool operator<(const rc_ptr< T > &other) const
Definition rcptr.h:667
rc_ptr(T *p, bool externalowner)
Definition rcptr.h:653
rc_ptr(std::auto_ptr< U > r)
Definition rcptr.h:661
void reset(T *p=NULL)
Definition rcptr.h:664
rc_ptr(T *p)
Definition rcptr.h:652
T * get() const
Definition rcptr.h:666
A ref is a const_ref which can reference non constant objects.
Definition rcptr.h:467
ref(T *pObject)
Definition rcptr.h:480
ref< T > & operator=(const ref< T > &other)
Definition rcptr.h:503
ref(const ref< T > &other)
Definition rcptr.h:492
T * operator->() const
Definition rcptr.h:508
ref(std::auto_ptr< U > r)
Definition rcptr.h:489
T referenced_type
Definition rcptr.h:472
T * pointer() const
Definition rcptr.h:516
ref(T *pObject, bool externalowner)
Definition rcptr.h:481
ref(const ref< R > &other)
Definition rcptr.h:495
T & operator*() const
Definition rcptr.h:512
friend class const_ref
Definition rcptr.h:468
T * release()
Definition rcptr.h:499
STL namespace.