Back to index

nux  3.0.0
ObjectPtr.h
Go to the documentation of this file.
00001 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
00002 /*
00003  * Copyright 2010-2011 Inalogic® Inc.
00004  *
00005  * This program is free software: you can redistribute it and/or modify it
00006  * under the terms of the GNU Lesser General Public License, as
00007  * published by the  Free Software Foundation; either version 2.1 or 3.0
00008  * of the License.
00009  *
00010  * This program is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranties of
00012  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00013  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00014  * License for more details.
00015  *
00016  * You should have received a copy of both the GNU Lesser General Public
00017  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00018  *
00019  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00020  *
00021  */
00022 
00023 
00024 #ifndef NUXCORE_OBJECTPTR_H
00025 #define NUXCORE_OBJECTPTR_H
00026 
00027 #include <sigc++/connection.h>
00028 #include <sigc++/functors/mem_fun.h>
00029 
00030 namespace nux
00031 {
00032   template <typename T>
00033   class ObjectWeakPtr;
00034 
00035   template <typename T>
00036   class ObjectPtr;
00037 
00039   template <typename T>
00040   class ObjectPtr
00041   {
00042   public:
00044     ObjectPtr()
00045       : ptr_(NULL)
00046     {
00047     }
00048 
00050     ObjectPtr(ObjectPtr<T> const& other)
00051       : ptr_(other.ptr_)
00052     {
00053       if (ptr_)
00054       {
00055         ptr_->objectptr_count_->Increment();
00056         ptr_->Reference();
00057       }
00058     }
00059 
00061 
00067     template <typename O>
00068     ObjectPtr(ObjectPtr<O> const& other)
00069       : ptr_(NULL)
00070     {
00071       if (other.ptr_ &&
00072           other.ptr_->Type().IsDerivedFromType(T::StaticObjectType))
00073       {
00074         ptr_ = static_cast<T*>(other.ptr_);
00075         ptr_->objectptr_count_->Increment();
00076         ptr_->Reference();
00077       }
00078     }
00079 
00081 
00089     explicit ObjectPtr(T *ptr, bool WarnMissuse = false)
00090       : ptr_(NULL)
00091     {
00092       if (ptr)
00093       {
00094         if (WarnMissuse && (!ptr->OwnsTheReference()))
00095         {
00096           nuxDebugMsg (TEXT ("[ObjectPtr::ObjectPtr] Warning: Constructing a smart pointer from an object with a floating reference.") );
00097         }
00098 
00099         ptr_ = ptr;
00100         ptr_->objectptr_count_->Increment();
00101         ptr_->Reference();
00102       }
00103     }
00104 
00106 
00114     template <typename O>
00115     explicit ObjectPtr(O *ptr, bool WarnMissuse = false)
00116       : ptr_(NULL)
00117     {
00118       if (ptr &&
00119           ptr->Type().IsDerivedFromType(T::StaticObjectType))
00120       {
00121         if (WarnMissuse && (!ptr->OwnsTheReference()))
00122         {
00123           nuxDebugMsg (TEXT ("[ObjectPtr::ObjectPtr] Warning: Constructing a smart pointer from an object with a floating reference.") );
00124         }
00125 
00126         ptr_ = static_cast<T*>(ptr);
00127         ptr_->objectptr_count_->Increment();
00128         ptr_->Reference();
00129       }
00130     }
00131 
00133     void Adopt(T* ptr)
00134     {
00135         ObjectPtr<T> temp(ptr);
00136         Swap(temp);
00137         // Now we want to release the reference that was added on construction,
00138         // but keep the smart pointer count.
00139         if (ptr_)
00140           ptr_->UnReference();
00141     }
00142 
00143 
00145 
00148     ObjectPtr& operator=(T* ptr)
00149     {
00150         ObjectPtr<T> temp(ptr);
00151         Swap(temp);
00152         return *this;
00153     }
00154 
00156 
00159     ObjectPtr& operator=(ObjectPtr<T> const& other)
00160     {
00161         ObjectPtr<T> temp(other);
00162         Swap(temp);
00163         return *this;
00164     }
00165 
00167 
00170     template <typename O>
00171     ObjectPtr& operator=(ObjectPtr<O> const& other)
00172     {
00173         ObjectPtr<T> temp(other);
00174         Swap(temp);
00175         return *this;
00176     }
00177 
00178     ~ObjectPtr()
00179     {
00180       ReleaseReference();
00181     }
00182 
00183     T& operator*() const
00184     {
00185       nuxAssert(ptr_ != 0);
00186       return *ptr_;
00187     }
00188 
00189     T* operator->() const
00190     {
00191       nuxAssert(ptr_ != 0);
00192       return ptr_;
00193     }
00194 
00196 
00201     T* GetPointer () const
00202     {
00203       return ptr_;
00204     }
00205 
00207 
00210     void Swap (ObjectPtr<T>& other)
00211     {
00212         std::swap(ptr_, other.ptr_);
00213     }
00214 
00215     operator bool() const
00216     {
00217         return bool(ptr_);
00218     }
00219 
00221 
00224     bool operator() () const
00225     {
00226         return bool(ptr_);
00227     }
00228 
00230 
00233     bool IsNull() const
00234     {
00235         return !IsValid();
00236     }
00237 
00239 
00242     bool IsValid() const
00243     {
00244       return (ptr_ != NULL) ? true : false;
00245     }
00246 
00247     bool operator < (T *ptr) const
00248     {
00249       return (ptr_ < ptr);
00250     }
00251 
00252     bool operator > (T *ptr) const
00253     {
00254       return (ptr_ > ptr);
00255     }
00256 
00257     bool operator < (ObjectPtr<T> other) const
00258     {
00259       return (ptr_ < other.ptr_);
00260     }
00261 
00262     bool operator > (ObjectPtr<T> other) const
00263     {
00264       return (ptr_ > other.ptr_);
00265     }
00266 
00267     bool operator == (T *ptr) const
00268     {
00269       return ptr_ == ptr;
00270     }
00271 
00272     template <typename U>
00273     bool operator != (U other) const
00274     {
00275       return !(*this == other);
00276     }
00277 
00278     template <typename U>
00279     bool operator == (U* ptr) const
00280     {
00281       if (ptr && (!ptr->Type().IsDerivedFromType(T::StaticObjectType)))
00282         return false;
00283 
00284       return ptr_ == static_cast<T*>(ptr);
00285     }
00286 
00287     template <typename U>
00288     bool operator == (ObjectPtr<U> const& other) const
00289     {
00290       if (other.ptr_ &&
00291           (!other.ptr_->Type().IsDerivedFromType (T::StaticObjectType) ) )
00292         return false;
00293 
00294       return ptr_ == static_cast<T*>(other.ptr_);
00295     }
00296 
00297     template <typename U>
00298     bool operator == (ObjectWeakPtr<U> const& other) const
00299     {
00300       if (other.ptr_ &&
00301           (!other.ptr_->Type().IsDerivedFromType (T::StaticObjectType) ) )
00302         return false;
00303 
00304       return ptr_ == static_cast<T*>(other.ptr_);
00305     }
00306 
00308 
00314     bool Release()
00315     {
00316       return ReleaseReference();
00317     }
00318 
00319   private:
00320 
00321     bool ReleaseReference()
00322     {
00323       if (!ptr_)
00324       {
00325         return false;
00326       }
00327 
00328       // Decrease the number of strong reference on the hosted pointer.
00329       ptr_->objectptr_count_->Decrement();
00330       bool destroyed = ptr_->UnReference();
00331       ptr_ = NULL;
00332       return destroyed;
00333     }
00334 
00335     T* ptr_;
00336 
00337     template <typename O>
00338     friend class ObjectPtr;
00339 
00340     template <typename O>
00341     friend class ObjectWeakPtr;
00342   };
00343 
00344 
00346 
00353   template <typename T>
00354   class ObjectWeakPtr
00355   {
00356   public:
00358     ObjectWeakPtr()
00359       : ptr_(NULL)
00360     {
00361     }
00362 
00364 
00372     explicit ObjectWeakPtr(T* ptr)
00373       : ptr_(ptr)
00374     {
00375       ConnectListener();
00376     }
00377 
00379 
00387     template <typename O>
00388     explicit ObjectWeakPtr(O* ptr, bool WarnMissuse = false)
00389       : ptr_(NULL)
00390     {
00391       if (ptr &&
00392           (ptr->Type().IsDerivedFromType(T::StaticObjectType)))
00393       {
00394         ptr_ = static_cast<T*>(ptr);
00395         ConnectListener();
00396       }
00397     }
00398 
00400 
00403     ObjectWeakPtr(ObjectWeakPtr<T> const& other)
00404       : ptr_(other.ptr_)
00405     {
00406       ConnectListener();
00407     }
00408 
00410 
00413     template <typename O>
00414     ObjectWeakPtr(const ObjectWeakPtr<O>& other)
00415       : ptr_(NULL)
00416     {
00417       if (other.ptr_ &&
00418           (other.ptr_->Type().IsDerivedFromType(T::StaticObjectType)))
00419       {
00420         ptr_ = static_cast<T*>(other.ptr_);
00421         ConnectListener();
00422       }
00423     }
00424 
00426 
00429     template <typename O>
00430     ObjectWeakPtr(const ObjectPtr<O> &other)
00431       : ptr_(NULL)
00432     {
00433       if (other.ptr_ &&
00434           (other.ptr_->Type().IsDerivedFromType(T::StaticObjectType)))
00435       {
00436         ptr_ = static_cast<T*>(other.ptr_);
00437         ConnectListener();
00438       }
00439     }
00440 
00442 
00445     ObjectWeakPtr& operator = (ObjectWeakPtr<T> const& other)
00446     {
00447       Disconnect();
00448       ptr_ = other.ptr_;
00449       ConnectListener();
00450       return *this;
00451     }
00452 
00453     // Warning: We are not sure that other.ptr_ is valid.
00454     // Warning: Cannot call other.ptr_->Type().IsDerivedFromType (T::StaticObjectType)
00456 
00459     template <typename O>
00460     ObjectWeakPtr &operator = (const ObjectWeakPtr<O>& other)
00461     {
00462       Disconnect();
00463       if (other.ptr_ &&
00464           other.ptr_->Type().IsDerivedFromType(T::StaticObjectType))
00465       {
00466         ptr_ = static_cast<T*>(other.ptr_);
00467         ConnectListener();
00468       }
00469       return *this;
00470     }
00471 
00473 
00476     template <typename O>
00477     ObjectWeakPtr &operator = (const ObjectPtr<O>& other)
00478     {
00479       Disconnect();
00480       if (other.ptr_ &&
00481           other.ptr_->Type().IsDerivedFromType(T::StaticObjectType))
00482       {
00483         ptr_ = static_cast<T*>(other.ptr_);
00484         ConnectListener();
00485       }
00486       return *this;
00487     }
00488 
00490 
00496     ObjectWeakPtr& operator = (T* ptr)
00497     {
00498       Disconnect();
00499       ptr_ = ptr;
00500       ConnectListener();
00501       return *this;
00502     }
00503 
00504     template <typename O>
00505     ObjectWeakPtr &operator = (O* ptr)
00506     {
00507       Disconnect();
00508       if (ptr &&
00509           ptr->Type().IsDerivedFromType(T::StaticObjectType))
00510       {
00511         ptr_ = static_cast<T*>(ptr);
00512         ConnectListener();
00513       }
00514       return *this;
00515     }
00516 
00517     ~ObjectWeakPtr()
00518     {
00519       Disconnect();
00520     }
00521 
00522     T& operator* () const
00523     {
00524       nuxAssert (ptr_ != 0);
00525       return *(const_cast<T*>(ptr_));
00526     }
00527 
00528     T* operator -> () const
00529     {
00530       nuxAssert (ptr_ != 0);
00531       return const_cast<T*>(ptr_);
00532     }
00533 
00534     bool operator < (T *ptr) const
00535     {
00536       return (ptr_ < ptr);
00537     }
00538 
00539     bool operator > (T *ptr) const
00540     {
00541       return (ptr_ > ptr);
00542     }
00543 
00544     bool operator < (ObjectWeakPtr<T> other) const
00545     {
00546       return (ptr_ < other.ptr_);
00547     }
00548 
00549     bool operator > (ObjectWeakPtr<T> other) const
00550     {
00551       return (ptr_ > other.ptr_);
00552     }
00553 
00554     template <typename U>
00555     bool operator != (U other) const
00556     {
00557       return !(*this == other);
00558     }
00559     bool operator == (T *ptr) const
00560     {
00561       return ptr_ == ptr;
00562     }
00563 
00564     template<typename U>
00565     bool operator == (U *ptr) const
00566     {
00567       if (ptr && (!ptr->Type().IsDerivedFromType (T::StaticObjectType) ) )
00568         return false;
00569 
00570       return ptr_ == static_cast<T*>(ptr);
00571     }
00572 
00577     template<typename U>
00578     bool operator == (const ObjectWeakPtr<U>& other) const
00579     {
00580       if (other.ptr_ && (!other.ptr_->Type().IsDerivedFromType (T::StaticObjectType) ) )
00581         return false;
00582 
00583       return ptr_ == static_cast<T*>(other.ptr_);
00584     }
00585 
00590     template<typename U>
00591     bool operator == (const ObjectPtr<U>& other) const
00592     {
00593       if (other.ptr_ && (!other.ptr_->Type().IsDerivedFromType (T::StaticObjectType) ) )
00594         return false;
00595 
00596       return ptr_ == static_cast<T*>(other.ptr_);
00597     }
00598 
00600 
00603     bool operator() () const
00604     {
00605       return bool(ptr_);
00606     }
00607 
00609 
00612     bool IsValid() const
00613     {
00614       return (ptr_!= NULL) ? true : false;
00615     }
00616 
00618 
00621     bool IsNull() const
00622     {
00623       return !IsValid();
00624     }
00625 
00627 
00636     bool Release()
00637     {
00638         Disconnect();
00639         ptr_ = NULL;
00640         return false;
00641     }
00642 
00644 
00648     T* GetPointer () const
00649     {
00650       return ptr_;
00651     }
00652 
00653   private:
00654     void Disconnect()
00655     {
00656       if (destroy_listener_.connected())
00657         destroy_listener_.disconnect();
00658     }
00659 
00660     void ConnectListener()
00661     {
00662       if (ptr_)
00663       {
00664         sigc::slot<void, Object*> slot = sigc::mem_fun(this, &ObjectWeakPtr<T>::TargetDestroyed);
00665         destroy_listener_ = ptr_->object_destroyed.connect(slot);
00666       }
00667     }
00668 
00669     void TargetDestroyed(Object* ptr)
00670     {
00671         ptr_ = NULL;
00672         // rese the connetion too
00673         destroy_listener_ = sigc::connection();
00674     }
00675 
00676     T* ptr_;
00677     sigc::connection destroy_listener_;
00678 
00679     template <typename O>
00680     friend class ObjectWeakPtr;
00681 
00682     template<typename U>
00683     friend bool operator == (U *, const ObjectWeakPtr<U>& a);
00684 
00685     template<typename U>
00686     friend bool operator != (U *, const ObjectWeakPtr<U>& a);
00687 
00688     template <typename U, typename F>
00689     friend ObjectWeakPtr<U> staticCast (const ObjectWeakPtr<F>& from);
00690 
00691     template <typename U, typename F>
00692     friend ObjectWeakPtr<U> constCast (const ObjectWeakPtr<F>& from);
00693 
00694     template <typename U, typename F>
00695     friend ObjectWeakPtr<U> dynamicCast (const ObjectWeakPtr<F>& from);
00696 
00697     template <typename U, typename F>
00698     friend ObjectWeakPtr<U> checkedCast (const ObjectWeakPtr<F>& from);
00699 
00700     template <typename U, typename F>
00701     friend ObjectWeakPtr<U> queryCast (const ObjectWeakPtr<F>& from);
00702   };
00703 
00705 // globals
00706 
00707 
00708   template<typename T>
00709   inline bool operator == (T *ptr, const ObjectPtr<T>& a)
00710   {
00711     return a.ptr_ == ptr;
00712   }
00713 
00714   template<typename T>
00715   inline bool operator != (T *ptr, const ObjectPtr<T>& a)
00716   {
00717     return a.ptr_ != ptr;
00718   }
00719 
00720   template<typename T>
00721   inline bool operator == (T *ptr, const ObjectWeakPtr<T>& a)
00722   {
00723     return a.ptr_ == ptr;
00724   }
00725 
00726   template<typename T>
00727   inline bool operator != (T *ptr, const ObjectWeakPtr<T>& a)
00728   {
00729     return a.ptr_ != ptr;
00730   }
00731 
00732 }
00733 
00734 #endif
00735 
00736