Merge branch 'master' of https://scm.cri.ensmp.fr/git/Faustine
[Faustine.git] / interpreter / preprocessor / faust-0.9.47mr3 / architecture / osclib / faust / src / lib / smartpointer.h
1 /*
2
3 Copyright (C) 2011 Grame
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Grame Research Laboratory, 9 rue du Garet, 69001 Lyon - France
20 research@grame.fr
21
22 */
23
24 #ifndef __smartpointer__
25 #define __smartpointer__
26
27 #include <cassert>
28
29 namespace oscfaust
30 {
31
32 /*!
33 \brief the base class for smart pointers implementation
34
35 Any object that want to support smart pointers should
36 inherit from the smartable class which provides reference counting
37 and automatic delete when the reference count drops to zero.
38 */
39 class smartable {
40 private:
41 unsigned refCount;
42 public:
43 //! gives the reference count of the object
44 unsigned refs() const { return refCount; }
45 //! addReference increments the ref count and checks for refCount overflow
46 void addReference() { refCount++; assert(refCount != 0); }
47 //! removeReference delete the object when refCount is zero
48 void removeReference() { if (--refCount == 0) delete this; }
49
50 protected:
51 smartable() : refCount(0) {}
52 smartable(const smartable&): refCount(0) {}
53 //! destructor checks for non-zero refCount
54 virtual ~smartable() { assert (refCount == 0); }
55 smartable& operator=(const smartable&) { return *this; }
56 };
57
58 /*!
59 \brief the smart pointer implementation
60
61 A smart pointer is in charge of maintaining the objects reference count
62 by the way of pointers operators overloading. It supports class
63 inheritance and conversion whenever possible.
64 \n Instances of the SMARTP class are supposed to use \e smartable types (or at least
65 objects that implements the \e addReference and \e removeReference
66 methods in a consistent way).
67 */
68 template<class T> class SMARTP {
69 private:
70 //! the actual pointer to the class
71 T* fSmartPtr;
72
73 public:
74 //! an empty constructor - points to null
75 SMARTP() : fSmartPtr(0) {}
76 //! build a smart pointer from a class pointer
77 SMARTP(T* rawptr) : fSmartPtr(rawptr) { if (fSmartPtr) fSmartPtr->addReference(); }
78 //! build a smart pointer from an convertible class reference
79 template<class T2>
80 SMARTP(const SMARTP<T2>& ptr) : fSmartPtr((T*)ptr) { if (fSmartPtr) fSmartPtr->addReference(); }
81 //! build a smart pointer from another smart pointer reference
82 SMARTP(const SMARTP& ptr) : fSmartPtr((T*)ptr) { if (fSmartPtr) fSmartPtr->addReference(); }
83
84 //! the smart pointer destructor: simply removes one reference count
85 ~SMARTP() { if (fSmartPtr) fSmartPtr->removeReference(); }
86
87 //! cast operator to retrieve the actual class pointer
88 operator T*() const { return fSmartPtr; }
89
90 //! '*' operator to access the actual class pointer
91 T& operator*() const {
92 // checks for null dereference
93 assert (fSmartPtr != 0);
94 return *fSmartPtr;
95 }
96
97 //! operator -> overloading to access the actual class pointer
98 T* operator->() const {
99 // checks for null dereference
100 assert (fSmartPtr != 0);
101 return fSmartPtr;
102 }
103
104 //! operator = that moves the actual class pointer
105 template <class T2>
106 SMARTP& operator=(T2 p1_) { *this=(T*)p1_; return *this; }
107
108 //! operator = that moves the actual class pointer
109 SMARTP& operator=(T* p_) {
110 // check first that pointers differ
111 if (fSmartPtr != p_) {
112 // increments the ref count of the new pointer if not null
113 if (p_ != 0) p_->addReference();
114 // decrements the ref count of the old pointer if not null
115 if (fSmartPtr != 0) fSmartPtr->removeReference();
116 // and finally stores the new actual pointer
117 fSmartPtr = p_;
118 }
119 return *this;
120 }
121 //! operator < to support SMARTP map with Visual C++
122 bool operator<(const SMARTP<T>& p_) const { return fSmartPtr < ((T *) p_); }
123 //! operator = to support inherited class reference
124 SMARTP& operator=(const SMARTP<T>& p_) { return operator=((T *) p_); }
125 //! dynamic cast support
126 template<class T2> SMARTP& cast(T2* p_) { return operator=(dynamic_cast<T*>(p_)); }
127 //! dynamic cast support
128 template<class T2> SMARTP& cast(const SMARTP<T2>& p_) { return operator=(dynamic_cast<T*>(p_)); }
129 };
130
131 }
132
133 #endif