cartobase 6.0.16
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 );
98protected:
99 /* if T has a release() method, there will be an ambiguity in
100 RefConstruction<T>::release, since RefConstruction inherits T and
101 DefaultRefConstruction. Then we will need to specialize
102 RefConstruction for these classes and overload release() there.
103 */
104 template <class T>
105 static const T *release( const_ref<T> * );
106};
107
108#endif // DOXYGEN_HIDE_INTERNAL_CLASSES
109
113#ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
114: public virtual DefaultRefConstruction
115#endif // DOXYGEN_HIDE_INTERNAL_CLASSES
116{
117 template <class T> friend class ref;
118 template <class T> friend class const_ref;
119 template <class T> friend class shared_ptr;
120 friend class rc_ptr_trick;
121
122 template <class T>
123 static void destroy( const_ref<T> * );
124 template <class T>
125 static void construct( const_ref<T> *, const T *, bool externalowner );
126 template <class T>
127 static const T *release( const_ref<T> * );
128
129public:
130#ifdef CARTO_THREADED_RCPTR
131 typedef boost::detail::atomic_count RefCounterType;
132#else
133 typedef int RefCounterType;
134#endif
135
136private:
137 mutable RefCounterType _refCounter;
138
139public:
140
141 inline RCObject() : _refCounter( 0 ) {}
142
143 inline RCObject( const RCObject & )
144 : _refCounter( 0 ) {}
145
146 inline RCObject & operator = ( const RCObject & ) { return *this; }
147
148 inline virtual ~RCObject()
149 {
150 // set counter to 0 in case of forced deletion
151 long refCounter = _refCounter;
152#ifdef CARTO_DEBUG
153 if( refCounter > 0 )
154 std::cerr << "RCObject destructor called while " << refCounter
155 << " references are still alive on object " << this
156 << std::endl;
157#endif
158 if( refCounter > 0 )
159 for( long i=0; i<refCounter; ++i )
160 --_refCounter;
161 else
162 for( long i=0; i<-refCounter; ++i )
163 ++_refCounter;
164 }
165};
166
167
168class rc_ptr_trick;
169
170
173#ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
182template <class T>
183class RefConstruction : T, virtual DefaultRefConstruction
184{
185 template <class R> friend class ref;
186 template <class R> friend class const_ref;
187
192 RefConstruction();
193};
194
202template <class T>
204{
205 template <class R> friend class const_ref;
206 template <class R> friend class ref;
208 friend class RCObject;
209 friend class rc_ptr_trick;
210
212 T *_ref;
213
214public:
215
216 inline int count() const
217 {
218 return ( _pcount ? *_pcount : 0 );
219 }
220};
221#endif // DOXYGEN_HIDE_INTERNAL_CLASSES
222
223
226
294template <class T>
296#ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
297: public RefData<T>
298#endif // DOXYGEN_HIDE_INTERNAL_CLASSES
299{
300
301#ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
303 friend class RCObject;
304#endif // DOXYGEN_HIDE_INTERNAL_CLASSES
305 template <class R> friend class ref;
306
307public:
308
310 inline const_ref() { this->_pcount = 0; this->_ref = 0; }
311
312 inline explicit const_ref( const T *pObject )
313 {
314 RefConstruction<T>::construct( this, pObject, false );
315 }
316
317 inline explicit const_ref( const T *pObject, bool externalowner )
318 {
319 RefConstruction<T>::construct( this, pObject, externalowner );
320 }
321
322#if __cplusplus >= 201103L
323 // Only unique_ptr with the default deleter can be converted, because
324 // const_ref does not support custom deleters (it calls the delete operator
325 // upon destruction, just like std::default_delete).
326 template< class U >
327 const_ref( std::unique_ptr<U>&& r )
328 {
329 RefConstruction<T>::construct( this, r.release(), false );
330 }
331#else
332 template< class U >
333 const_ref( std::auto_ptr<U> r )
334 {
335 RefConstruction<T>::construct( this, r.release(), false );
336 }
337#endif
338
339 inline const_ref( const ref<T> &other ) {
340#ifdef DEBUG_REF
341 std::cout << "New ref from other ref (" << other._ref << ")" << std::endl;
342#endif
343 if( other._pcount && *other._pcount >= 0 )
344 ++(*other._pcount);
345 this->_pcount = other._pcount;
346 this->_ref = other._ref;
347 }
348
349 inline const_ref( const const_ref<T> &other ) {
350#ifdef DEBUG_REF
351 std::cout << "New ref from other ref (" << other._ref << ")" << std::endl;
352#endif
353 if( other._pcount && *other._pcount >= 0 )
354 ++(*other._pcount);
355 this->_pcount = other._pcount;
356 this->_ref = other._ref;
357 }
358
359 template <class R>
360 inline const_ref( const ref<R> &o ){
361 const RefData<R> &other = o;
362#ifdef DEBUG_REF
363 std::cout << "New ref from other ref with implicit cast (" << other._ref
364 << ")" << std::endl;
365#endif
366 if( other._pcount && *other._pcount >= 0 )
367 ++(*other._pcount);
368 this->_pcount = other._pcount;
369 this->_ref = other._ref;
370 }
371
372 template <class R>
373 inline const_ref( const const_ref<R> &other ){
374#ifdef DEBUG_REF
375 std::cout << "New ref from other ref with implicit cast (" << other._ref << ")" << std::endl;
376#endif
377 if( other._pcount && *other._pcount >= 0 )
378 ++(*other._pcount);
379 this->_pcount = other._pcount;
380 this->_ref = other._ref;
381 }
382
383 inline ~const_ref() { RefConstruction<T>::destroy( this ); }
384
385 // const_ref<T> &operator =( const T *pObject );
388
389 inline bool isNull() const { return this->_pcount == NULL; }
390 inline bool operator ==( const ref<T> &other ) const { return this->_ref == other._ref; }
391 inline bool operator ==( const T *pointer ) const { return this->_ref == pointer; }
392 inline bool operator ==( const const_ref<T> &other ) const { return this->_ref == other._ref; }
393 inline bool operator !=( const ref<T> &other ) const { return this->_ref != other._ref; }
394 inline bool operator !=( const const_ref<T> &other ) const { return this->_ref != other._ref; }
395 inline bool operator !=( const T *pointer ) const { return this->_ref != pointer; }
396
397 inline const T *operator ->() const {
398 return static_cast<const T *>( this->_ref );
399 }
400
401 inline const T &operator *() const {
402 return *static_cast<const T *>( this->_ref );
403 }
404
405 inline const T *pointer() const {
406 return static_cast<const T *>( this->_ref );
407 }
408
409 inline int refCount() const
410 {
411 return this->_pcount ? *this->_pcount : 0;
412 }
413};
414
415
417 /*
418template <class T>
419const_ref<T> &const_ref<T>::operator =( const T *pObject ) {
420#ifdef DEBUG_REF
421 std::cout << "ref (" << this->_ref << ") = " << pObject << std::endl;
422#endif
423 if ( this->_ref != pObject ) {
424 RefConstruction<T>::destroy( this );
425 RefConstruction<T>::construct( this, pObject, false );
426 }
427 return *this;
428}
429 */
430
432template <class T>
434#ifdef DEBUG_REF
435 std::cout << "ref (" << this->_ref << ") = ref (" << other._ref << ")"
436 << std::endl;
437#endif
438 if ( this->_ref != other._ref )
439 {
440 if( other._pcount && *other._pcount >= 0 )
441 ++(*other._pcount);
442 RefConstruction<T>::destroy( this );
443 this->_pcount = other._pcount;
444 this->_ref = other._ref;
445 }
446 return *this;
447}
448
450template <class T>
452#ifdef DEBUG_REF
453 std::cout << "ref (" << this->_ref << ") = ref (" << other._ref << ")"
454 << std::endl;
455#endif
456 if ( this != &other && this->_ref != other._ref )
457 {
458 if( other._pcount && *other._pcount >= 0 )
459 ++(*other._pcount);
460 RefConstruction<T>::destroy( this );
461 this->_pcount = other._pcount;
462 this->_ref = other._ref;
463 }
464 return *this;
465}
466
467
471template <class T>
472class ref : public const_ref<T>
473{
474 template <class R> friend class const_ref;
475
476public:
477
479
480 inline ref() : const_ref<T>() {
481#ifdef DEBUG_REF
482 std::cout << "New empty ref" << std::endl;
483#endif
484 }
485
486 inline explicit ref( T *pObject ) : const_ref<T>( pObject ) {}
487 inline explicit ref( T *pObject, bool externalowner )
488 : const_ref<T>( pObject, externalowner ) {}
489
490#if __cplusplus >= 201103L
491 template< class U >
492 ref( std::unique_ptr<U>&& r ) : const_ref<T>( std::move(r) ) {}
493#else
494 template< class U >
495 ref( std::auto_ptr<U> r ) : const_ref<T>( r ) {}
496#endif
497
498 inline ref( const ref<T> &other ) : const_ref<T>( other ) {}
499
500 template <class R>
501 inline ref( const ref<R> &other ) : const_ref<T>( other ) {}
502
503 inline ~ref() {}
504
505 inline T *release() {
506 return const_cast<T *>( RefConstruction<T>::release( this ) );
507 }
508
509 inline ref<T> &operator =( const ref<T> &other ) {
510 this->const_ref<T>::operator =( other );
511 return *this;
512 }
513
514 inline T *operator ->() const {
515 return static_cast<T *>( this->_ref );
516 }
517
518 inline T &operator *() const {
519 return *static_cast<T *>( this->_ref );
520 }
521
522 inline T *pointer() const {
523 return static_cast<T *>( this->_ref );
524 }
525
526};
527
528
529
531#ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
532template <class T>
533void DefaultRefConstruction::construct( const_ref<T> *r, const T *pObject,
534 bool externalowner )
535{
536#ifdef DEBUG_REF
537 std::cout << "New ref (" << pObject << ")" << std::endl;
538#endif
539 if ( pObject && !externalowner )
540 r->_pcount = new RCObject::RefCounterType( 1 );
541 else r->_pcount = NULL;
542 r->_ref = const_cast<T *>( pObject );
543}
544
546template <class T>
547void DefaultRefConstruction::destroy( const_ref<T> *r ) {
548#ifdef DEBUG_REF
549 std::cout << "Deleting ref (" << r->_ref << ")" << std::endl;
550#endif
551 if ( r->_pcount && --(*r->_pcount) == 0 )
552 {
553#ifdef DEBUG_REF
554 std::cout << "Deleting ref object (" << r->_ref << ")" << std::endl;
555#endif
556 delete r->_pcount;
557 delete static_cast<T *>( r->_ref );
558 }
559}
560
562template <class T>
564#ifdef DEBUG_REF
565 std::cout << "Releasing ref (" << r->_ref << ")" << std::endl;
566#endif
567 const T * const result = r->_ref;
568 if ( r->_pcount && --(*r->_pcount) == 0 )
569 {
570 delete r->_pcount;
571 r->_pcount = 0;
572 }
573 r->_ref = NULL;
574 return result;
575}
576#endif // DOXYGEN_HIDE_INTERNAL_CLASSES
577
580
581
582
583
585template <class T>
586void RCObject::construct( const_ref<T> *r, const T * pObject,
587 bool externalowner )
588{
589#ifdef DEBUG_REF
590 std::cout << "New RCObject (" << pObject << ")" << std::endl;
591#endif
592 if( pObject )
593 {
594 long x = pObject->_refCounter;
595 if( externalowner && x == 0 )
596 {
597 --pObject->_refCounter;
598 // r->_pcount = NULL;
599 }
600 else if( x >= 0 )
601 ++pObject->_refCounter;
602 r->_pcount = &pObject->_refCounter;
603 }
604 else
605 r->_pcount = NULL;
606 r->_ref = const_cast<T *>( pObject );
607}
608
610template <class T>
611void RCObject::destroy( const_ref<T> *r )
612{
613#ifdef DEBUG_REF
614 std::cout << "RCObject::destroy (" << r->_ref << ")" << std::endl;
615 if( r->_pcount )
616 std::cout << " count: " << *r->_pcount << std::endl;
617 else
618 std::cout << " no counter\n";
619#endif
620 if( r->_pcount && --(*r->_pcount) == 0 )
621 {
622#ifdef DEBUG_REF
623 std::cout << "Deleting RCObject object (" << r->_ref << ")" << std::endl;
624#endif
625 delete static_cast<T *>( r->_ref );
626 }
627}
628
630template <class T>
631const T *RCObject::release( const_ref<T> *r ) {
632#ifdef DEBUG_REF
633 std::cout << "Releasing RCObject (" << r->_ref << ")" << std::endl;
634#endif
635 const T * const result = r->_ref;
636 if ( r->_pcount && *r->_pcount >= 0 )
637 --(*r->_pcount);
638 r->_pcount = 0;
639 r->_ref = 0;
640 return result;
641}
642
643
644template <typename T>
645class rc_ptr : public ref<T>
646{
647public:
648#ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
650 {
651 protected:
652 void operator delete( void* );
653 void operator delete[]( void* );
654 };
655#endif
656
657 inline rc_ptr() {}
658 inline explicit rc_ptr( T *p ) : ref<T>( p ) {}
659 inline explicit rc_ptr( T *p, bool externalowner )
660 : ref<T>( p, externalowner ) {}
661
662#if __cplusplus >= 201103L
663 template< class U >
664 rc_ptr( std::unique_ptr<U>&& r ) : ref<T>( std::move(r) ) {}
665#else
666 template< class U >
667 rc_ptr( std::auto_ptr<U> r ) : ref<T>( r ) {}
668#endif
669
670 inline void reset( T *p = NULL )
671 { *static_cast< ref<T> * >( this ) = ref<T>( p ); }
672 inline T *get() const { return this->pointer(); }
673 inline bool operator <( const rc_ptr<T> &other ) const {
674 return this->pointer() < other.pointer();
675 }
676
677#ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
678 inline operator insipid*() const
679 {
680 return reinterpret_cast< insipid* >( this->pointer() );
681 }
682#endif
683};
684
685
686
687template <>
688class RefConstruction< char > : DefaultRefConstruction
689{
690
691 private:
692
693 template < class R > friend class ref;
694 template < class R > friend class const_ref;
695
696 RefConstruction();
697
698
699};
700
701
702template <>
703class RefConstruction< unsigned char > : DefaultRefConstruction
704{
705
706 private:
707
708 template < class R > friend class ref;
709 template < class R > friend class const_ref;
710
711 RefConstruction();
712
713
714};
715
716
717template <>
718class RefConstruction< short > : DefaultRefConstruction
719{
720
721 private:
722
723 template < class R > friend class ref;
724 template < class R > friend class const_ref;
725
726 RefConstruction();
727
728
729};
730
731
732template <>
733class RefConstruction< unsigned short > : DefaultRefConstruction
734{
735
736 private:
737
738 template < class R > friend class ref;
739 template < class R > friend class const_ref;
740
741 RefConstruction();
742
743
744};
745
746
747template <>
748class RefConstruction< int > : DefaultRefConstruction
749{
750
751 private:
752
753 template < class R > friend class ref;
754 template < class R > friend class const_ref;
755
756 RefConstruction();
757
758
759};
760
761
762template <>
763class RefConstruction< unsigned int > : DefaultRefConstruction
764{
765
766 private:
767
768 template < class R > friend class ref;
769 template < class R > friend class const_ref;
770
771 RefConstruction();
772
773
774};
775
776
777template <>
778class RefConstruction< long > : DefaultRefConstruction
779{
780
781 private:
782
783 template < class R > friend class ref;
784 template < class R > friend class const_ref;
785
786 RefConstruction();
787
788
789};
790
791
792template <>
793class RefConstruction< unsigned long > : DefaultRefConstruction
794{
795
796 private:
797
798 template < class R > friend class ref;
799 template < class R > friend class const_ref;
800
801 RefConstruction();
802
803
804};
805
806
807template <>
808class RefConstruction< float > : DefaultRefConstruction
809{
810
811 private:
812
813 template < class R > friend class ref;
814 template < class R > friend class const_ref;
815
816 RefConstruction();
817
818
819};
820
821
822template <>
823class RefConstruction< double > : DefaultRefConstruction
824{
825
826 private:
827
828 template < class R > friend class ref;
829 template < class R > friend class const_ref;
830
831 RefConstruction();
832
833
834};
835
836
837} // namespace carto
838
839
840#endif
static const T * release(const_ref< T > *)
Definition rcptr.h:563
RCObject(const RCObject &)
Definition rcptr.h:143
RCObject & operator=(const RCObject &)
Definition rcptr.h:146
virtual ~RCObject()
Definition rcptr.h:148
friend class ref
Definition rcptr.h:117
friend class shared_ptr
Definition rcptr.h:119
int RefCounterType
Definition rcptr.h:133
friend class rc_ptr_trick
Definition rcptr.h:120
friend class const_ref
Definition rcptr.h:118
friend class ref
Definition rcptr.h:185
friend class const_ref
Definition rcptr.h:186
int count() const
Definition rcptr.h:216
friend class DefaultRefConstruction
Definition rcptr.h:207
friend class ref
Definition rcptr.h:206
friend class RCObject
Definition rcptr.h:208
friend class rc_ptr_trick
Definition rcptr.h:209
friend class const_ref
Definition rcptr.h:205
Constant Ref to an object of class T.
Definition rcptr.h:299
const_ref(const ref< T > &other)
Definition rcptr.h:339
bool operator!=(const ref< T > &other) const
Definition rcptr.h:393
const T * pointer() const
Definition rcptr.h:405
const_ref(const const_ref< R > &other)
Definition rcptr.h:373
const_ref(const T *pObject)
Definition rcptr.h:312
const_ref(std::auto_ptr< U > r)
Definition rcptr.h:333
friend class DefaultRefConstruction
Definition rcptr.h:302
const_ref(const ref< R > &o)
Definition rcptr.h:360
const_ref(const const_ref< T > &other)
Definition rcptr.h:349
bool operator==(const ref< T > &other) const
Definition rcptr.h:390
const_ref< T > & operator=(const ref< T > &other)
Definition rcptr.h:433
const T * operator->() const
Definition rcptr.h:397
friend class ref
Definition rcptr.h:305
friend class RCObject
Definition rcptr.h:303
bool isNull() const
Definition rcptr.h:389
const T & operator*() const
Definition rcptr.h:401
const_ref(const T *pObject, bool externalowner)
Definition rcptr.h:317
int refCount() const
Definition rcptr.h:409
bool operator<(const rc_ptr< T > &other) const
Definition rcptr.h:673
rc_ptr(T *p, bool externalowner)
Definition rcptr.h:659
rc_ptr(std::auto_ptr< U > r)
Definition rcptr.h:667
void reset(T *p=NULL)
Definition rcptr.h:670
rc_ptr(T *p)
Definition rcptr.h:658
T * get() const
Definition rcptr.h:672
A ref is a const_ref which can reference non constant objects.
Definition rcptr.h:473
ref(T *pObject)
Definition rcptr.h:486
ref< T > & operator=(const ref< T > &other)
Definition rcptr.h:509
ref(const ref< T > &other)
Definition rcptr.h:498
T * operator->() const
Definition rcptr.h:514
ref(std::auto_ptr< U > r)
Definition rcptr.h:495
T referenced_type
Definition rcptr.h:478
T * pointer() const
Definition rcptr.h:522
ref(T *pObject, bool externalowner)
Definition rcptr.h:487
ref(const ref< R > &other)
Definition rcptr.h:501
T & operator*() const
Definition rcptr.h:518
friend class const_ref
Definition rcptr.h:474
T * release()
Definition rcptr.h:505
STL namespace.