--- /dev/null
+/*
+
+ Copyright (C) 2011 Grame
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Grame Research Laboratory, 9 rue du Garet, 69001 Lyon - France
+ research@grame.fr
+
+*/
+
+#ifndef __smartpointer__
+#define __smartpointer__
+
+#include <cassert>
+
+namespace oscfaust
+{
+
+/*!
+\brief the base class for smart pointers implementation
+
+ Any object that want to support smart pointers should
+ inherit from the smartable class which provides reference counting
+ and automatic delete when the reference count drops to zero.
+*/
+class smartable {
+ private:
+ unsigned refCount;
+ public:
+ //! gives the reference count of the object
+ unsigned refs() const { return refCount; }
+ //! addReference increments the ref count and checks for refCount overflow
+ void addReference() { refCount++; assert(refCount != 0); }
+ //! removeReference delete the object when refCount is zero
+ void removeReference() { if (--refCount == 0) delete this; }
+
+ protected:
+ smartable() : refCount(0) {}
+ smartable(const smartable&): refCount(0) {}
+ //! destructor checks for non-zero refCount
+ virtual ~smartable() { assert (refCount == 0); }
+ smartable& operator=(const smartable&) { return *this; }
+};
+
+/*!
+\brief the smart pointer implementation
+
+ A smart pointer is in charge of maintaining the objects reference count
+ by the way of pointers operators overloading. It supports class
+ inheritance and conversion whenever possible.
+\n Instances of the SMARTP class are supposed to use \e smartable types (or at least
+ objects that implements the \e addReference and \e removeReference
+ methods in a consistent way).
+*/
+template<class T> class SMARTP {
+ private:
+ //! the actual pointer to the class
+ T* fSmartPtr;
+
+ public:
+ //! an empty constructor - points to null
+ SMARTP() : fSmartPtr(0) {}
+ //! build a smart pointer from a class pointer
+ SMARTP(T* rawptr) : fSmartPtr(rawptr) { if (fSmartPtr) fSmartPtr->addReference(); }
+ //! build a smart pointer from an convertible class reference
+ template<class T2>
+ SMARTP(const SMARTP<T2>& ptr) : fSmartPtr((T*)ptr) { if (fSmartPtr) fSmartPtr->addReference(); }
+ //! build a smart pointer from another smart pointer reference
+ SMARTP(const SMARTP& ptr) : fSmartPtr((T*)ptr) { if (fSmartPtr) fSmartPtr->addReference(); }
+
+ //! the smart pointer destructor: simply removes one reference count
+ ~SMARTP() { if (fSmartPtr) fSmartPtr->removeReference(); }
+
+ //! cast operator to retrieve the actual class pointer
+ operator T*() const { return fSmartPtr; }
+
+ //! '*' operator to access the actual class pointer
+ T& operator*() const {
+ // checks for null dereference
+ assert (fSmartPtr != 0);
+ return *fSmartPtr;
+ }
+
+ //! operator -> overloading to access the actual class pointer
+ T* operator->() const {
+ // checks for null dereference
+ assert (fSmartPtr != 0);
+ return fSmartPtr;
+ }
+
+ //! operator = that moves the actual class pointer
+ template <class T2>
+ SMARTP& operator=(T2 p1_) { *this=(T*)p1_; return *this; }
+
+ //! operator = that moves the actual class pointer
+ SMARTP& operator=(T* p_) {
+ // check first that pointers differ
+ if (fSmartPtr != p_) {
+ // increments the ref count of the new pointer if not null
+ if (p_ != 0) p_->addReference();
+ // decrements the ref count of the old pointer if not null
+ if (fSmartPtr != 0) fSmartPtr->removeReference();
+ // and finally stores the new actual pointer
+ fSmartPtr = p_;
+ }
+ return *this;
+ }
+ //! operator < to support SMARTP map with Visual C++
+ bool operator<(const SMARTP<T>& p_) const { return fSmartPtr < ((T *) p_); }
+ //! operator = to support inherited class reference
+ SMARTP& operator=(const SMARTP<T>& p_) { return operator=((T *) p_); }
+ //! dynamic cast support
+ template<class T2> SMARTP& cast(T2* p_) { return operator=(dynamic_cast<T*>(p_)); }
+ //! dynamic cast support
+ template<class T2> SMARTP& cast(const SMARTP<T2>& p_) { return operator=(dynamic_cast<T*>(p_)); }
+};
+
+}
+
+#endif