Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

spimpl.hpp

00001 /************************************************************************************
00002  *    This file is part of the MynahSA streaming and archiving toolkit              *
00003  *    Copyright (C) 2006 Mynah-Software Ltd. All Rights Reserved.                   *
00004  *                                                                                  *
00005  *    This program is free software; you can redistribute it and/or modify          *
00006  *    it under the terms of the GNU General Public License, version 2               *
00007  *    as published by the Free Software Foundation.                                 *
00008  *                                                                                  *
00009  *    This program is distributed in the hope that it will be useful,               *
00010  *    but WITHOUT ANY WARRANTY; without even the implied warranty of                *
00011  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 *
00012  *    GNU General Public License for more details.                                  *
00013  *                                                                                  *
00014  *    You should have received a copy of the GNU General Public License along       *
00015  *    with this program; if not, write to the Free Software Foundation, Inc.,       *
00016  *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.                   *
00017  *                                                                                  *
00018  ************************************************************************************/
00019 
00020 #ifndef __sp_impl_hpp
00021 #define __sp_impl_hpp
00022 
00023 #ifdef MYNAHSA_USE_BOOST
00024 
00025 #include <boost/shared_ptr.hpp>
00026 #define SHARED_PTR boost::shared_ptr
00027 #define STATIC_PTR_CAST boost::static_pointer_cast
00028 
00029 #else
00030 
00031 #define SHARED_PTR MynahSA::SharedPtr  
00032 #define STATIC_PTR_CAST MynahSA::StaticPtrCast
00033 
00034 #include <mynahsa/thread.hpp>
00035 
00036 namespace MynahSA { 
00037 
00038   namespace Detail { 
00039     class SPBase { 
00040     public:
00041       inline SPBase() : _ptr(0), _count(0) { }
00042       inline SPBase(void* p) : _ptr(p), _count(0) { }
00043       inline virtual ~SPBase() { 
00044       }
00045     
00046       inline void ref() { 
00047         Lock l(_m);
00048         _count++;
00049       }
00050     
00051       inline void unref() { 
00052         Mutex::lock(_m);
00053         if (--_count == 0) { 
00054           // delete the object
00055           deleteMe();
00056           
00057           // unlock the mutex
00058           Mutex::unlock(_m);
00059           
00060           // delete us (which implicitly deletes the mutex)
00061           delete this;
00062           
00063         } else { 
00064           Mutex::unlock(_m);
00065         }
00066       }
00067 
00068       inline void* get() const { return _ptr; }
00069     
00070     protected:
00071       virtual void deleteMe() = 0;
00072     
00073       void* _ptr;
00074     
00075     private:
00076       unsigned int _count;
00077       
00078       Mutex _m;    
00079     };
00080     
00081     template <class L>
00082     class SPImpl : public SPBase { 
00083     public:
00084       inline SPImpl(L* p) : SPBase(p) { 
00085         ref();
00086       }
00087     
00088       inline ~SPImpl() { 
00089       }
00090       
00091     protected:
00092       void deleteMe() { 
00093         delete static_cast<L*>(_ptr);
00094         _ptr = 0;
00095       }
00096     };
00097   
00098   };
00099 
00112   template<class T>
00113   class SharedPtr { 
00114   public:
00115     template <class B,class A>
00116     friend SharedPtr<B> StaticPtrCast(const SharedPtr<A>& src);
00117   public:
00119     SharedPtr() : _spref(0) {
00120     }
00121       
00122     
00129     SharedPtr(T* p) : _spref(new Detail::SPImpl<T>(p)) { 
00130     }
00131       
00133     SharedPtr(const SharedPtr& p) : _spref(p._spref) {
00134       if (_spref) { 
00135         // up the reference count
00136         _spref->ref();
00137       }
00138     }
00139       
00140     
00148     SharedPtr(Detail::SPBase* p) : _spref(p) {
00149       if (p) { 
00150         p->ref();
00151       }
00152     }
00153     
00155     virtual ~SharedPtr() { 
00156       if (_spref) { 
00157         // drop reference count, deleting object if object is no longer referenced
00158         _spref->unref();
00159       }
00160     }
00161       
00163     T* get() const {
00164       if (_spref){ 
00165         return static_cast<T*>(_spref->get());
00166       } else { 
00167         return 0;
00168       }
00169     }
00170     
00172     T& operator*() const { 
00173       // note: this is a failure if pointer is zero! A throw should be placed here in the event that pointer is zero
00174       return *(static_cast<T*>(_spref->get()));
00175     }
00176   
00178     T* operator->() const { 
00179       return static_cast<T*>(_spref->get());
00180     }
00181   
00183     bool operator<(const SharedPtr& in) const { 
00184       return _spref->get() < in._spref->get();
00185     }
00186   
00188     SharedPtr& operator=(const SharedPtr& in) { 
00189       if (_spref) { 
00190         _spref->unref();
00191       }
00192       _spref = in._spref;
00193       // Note: Don't increment spref if null pointer!
00194       if (_spref) { 
00195         _spref->ref();
00196       }
00197   
00198       return *this;
00199     }
00200     
00202     bool operator==(const SharedPtr& in) const { 
00203       return _spref == in._spref;
00204     }
00205       
00207     bool operator==(T* ptr) const { 
00208       //  is    (spref 0)    yes                no
00209       return _spref == 0 ? (ptr == 0) : ptr == static_cast<T*>(_spref->get());
00210     }
00211       
00213     operator bool() const { 
00214       return _spref == 0 ? false : _spref->get() != 0;
00215     }
00216       
00218     template<class B>
00219     operator SharedPtr<B>() const { 
00220       // invalid pointer, cast zero to target
00221       if (!_spref->get()) { 
00222         return SharedPtr<B>();
00223       } 
00224       
00225       static_cast<B*>( static_cast<T*>(_spref->get()) ); // this is an assert - that static casting is allowed
00226       SharedPtr<B> dst(_spref);
00227       return dst;
00228     }
00229       
00230       
00231   private:
00233     Detail::SPBase* _spref;
00234   };
00235   
00236   
00237   
00244   template<>
00245   class SharedPtr<void> { 
00246     //template<class B>
00247     //friend SharedPtr<void> StaticPtrCast(const SharedPtr<B>&);
00248   
00249   
00250     template <class B,class A>
00251     friend SharedPtr<B> StaticPtrCast(const SharedPtr<A>& src);
00252   
00253   
00254   public:
00256     SharedPtr() : _spref(0) {
00257     }
00258   
00259     // cannot construct a void instance
00260       
00262     SharedPtr(const SharedPtr& p) : _spref(p._spref) {
00263       if (_spref) { 
00264         // up the reference count
00265         _spref->ref();
00266       }
00267     }
00268       
00269       
00270     SharedPtr(Detail::SPBase* p) : _spref(p) {
00271       if (p) { 
00272         p->ref();
00273       }
00274     }
00275       
00276     virtual ~SharedPtr() { 
00277       if (_spref) { 
00278         // drop reference count, deleting object if object is no longer referenced
00279         _spref->unref();
00280       }
00281     }
00282       
00284     void* get() const {
00285       if (_spref){ 
00286   
00287         return _spref->get();
00288       } else { 
00289         return 0;
00290       }
00291     }
00292     
00293     // no reference method
00294   
00295     bool operator<(const SharedPtr& in) const { 
00296       return _spref->get() < in._spref->get();
00297     }
00298   
00299     
00300     SharedPtr& operator=(const SharedPtr& in) { 
00301       if (_spref) { 
00302         _spref->unref();
00303       }
00304       _spref = in._spref;
00305       _spref->ref();
00306   
00307       return *this;
00308     }
00309     
00310     
00311     bool operator==(const SharedPtr& in) const { 
00312       return _spref == in._spref;
00313     }
00314       
00315     bool operator==(void* ptr) const { 
00316       //  is    (spref 0)    yes                no
00317       return _spref == 0 ? (ptr == 0) : ptr == static_cast<void*>(_spref->get());
00318     }
00319       
00320     operator bool() const { 
00321       return _spref == 0 ? false : _spref->get() != 0;
00322     }
00323     
00324     template<class B>
00325     operator SharedPtr<B>() const { 
00326       // invalid pointer, cast zero to target
00327       if (!_spref->get()) { 
00328         return SharedPtr<B>();
00329       } 
00330       // don't need the assertion, we know it will succeed already      
00331       SharedPtr<B> dst(_spref);
00332       return dst;
00333     }
00334     
00335       
00336       
00337   private:
00338     Detail::SPBase* _spref;
00339   };
00340   
00341   template <class B,class A>
00342   SharedPtr<B> StaticPtrCast(const SharedPtr<A>& src) {
00343     static_cast<B*>( static_cast<A*>(0)); // this is an assert - that static casting is allowed
00344     SharedPtr<B> dst(src._spref);
00345     return dst;
00346   }
00347   
00348 
00349 
00350 
00351 };
00352 
00353 #endif
00354 
00355 #endif