nux-1.16.0
ObjectPtr.h
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_(nullptr)
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_(nullptr)
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_(nullptr)
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_(nullptr)
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     const T* GetPointer () const
00202     {
00203       return ptr_;
00204     }
00205 
00207 
00212     T* GetPointer()
00213     {
00214       return ptr_;
00215     }
00216 
00218 
00221     void Swap (ObjectPtr<T>& other)
00222     {
00223         std::swap(ptr_, other.ptr_);
00224     }
00225 
00226     operator bool() const
00227     {
00228         return bool(ptr_);
00229     }
00230 
00232 
00235     bool operator() () const
00236     {
00237         return bool(ptr_);
00238     }
00239 
00241 
00244     bool IsNull() const
00245     {
00246         return !IsValid();
00247     }
00248 
00250 
00253     bool IsValid() const
00254     {
00255         return bool(ptr_);
00256     }
00257 
00258     bool operator < (T *ptr) const
00259     {
00260       return (ptr_ < ptr);
00261     }
00262 
00263     bool operator > (T *ptr) const
00264     {
00265       return (ptr_ > ptr);
00266     }
00267 
00268     bool operator < (ObjectPtr<T> other) const
00269     {
00270       return (ptr_ < other.ptr_);
00271     }
00272 
00273     bool operator > (ObjectPtr<T> other) const
00274     {
00275       return (ptr_ > other.ptr_);
00276     }
00277 
00278     bool operator == (T *ptr) const
00279     {
00280       return ptr_ == ptr;
00281     }
00282 
00283     template <typename U>
00284     bool operator != (U other) const
00285     {
00286       return !(*this == other);
00287     }
00288 
00289     template <typename U>
00290     bool operator == (U* ptr) const
00291     {
00292       if (ptr && (!ptr->Type().IsDerivedFromType(T::StaticObjectType)))
00293         return false;
00294 
00295       return ptr_ == static_cast<T*>(ptr);
00296     }
00297 
00298     template <typename U>
00299     bool operator == (ObjectPtr<U> const& other) const
00300     {
00301       if (other.ptr_ &&
00302           (!other.ptr_->Type().IsDerivedFromType (T::StaticObjectType) ) )
00303         return false;
00304 
00305       return ptr_ == static_cast<T*>(other.ptr_);
00306     }
00307 
00308     template <typename U>
00309     bool operator == (ObjectWeakPtr<U> const& other) const
00310     {
00311       if (other.ptr_ &&
00312           (!other.ptr_->Type().IsDerivedFromType (T::StaticObjectType) ) )
00313         return false;
00314 
00315       return ptr_ == static_cast<T*>(other.ptr_);
00316     }
00317 
00319 
00325     bool Release()
00326     {
00327       return ReleaseReference();
00328     }
00329 
00330   private:
00331 
00332     bool ReleaseReference()
00333     {
00334       if (!ptr_)
00335       {
00336         return false;
00337       }
00338 
00339       // Decrease the number of strong reference on the hosted pointer.
00340       ptr_->objectptr_count_->Decrement();
00341       bool destroyed = ptr_->UnReference();
00342       ptr_ = nullptr;
00343       return destroyed;
00344     }
00345 
00346     T* ptr_;
00347 
00348     template <typename O>
00349     friend class ObjectPtr;
00350 
00351     template <typename O>
00352     friend class ObjectWeakPtr;
00353   };
00354 
00355 
00357 
00364   template <typename T>
00365   class ObjectWeakPtr
00366   {
00367   public:
00369     ObjectWeakPtr()
00370       : ptr_(nullptr)
00371     {
00372     }
00373 
00375 
00383     explicit ObjectWeakPtr(T* ptr)
00384       : ptr_(ptr)
00385     {
00386       ConnectListener();
00387     }
00388 
00390 
00398     template <typename O>
00399     explicit ObjectWeakPtr(O* ptr, bool WarnMissuse = false)
00400       : ptr_(nullptr)
00401     {
00402       if (ptr &&
00403           (ptr->Type().IsDerivedFromType(T::StaticObjectType)))
00404       {
00405         ptr_ = static_cast<T*>(ptr);
00406         ConnectListener();
00407       }
00408     }
00409 
00411 
00414     ObjectWeakPtr(ObjectWeakPtr<T> const& other)
00415       : ptr_(other.ptr_)
00416     {
00417       ConnectListener();
00418     }
00419 
00421 
00424     template <typename O>
00425     ObjectWeakPtr(const ObjectWeakPtr<O>& other)
00426       : ptr_(nullptr)
00427     {
00428       if (other.ptr_ &&
00429           (other.ptr_->Type().IsDerivedFromType(T::StaticObjectType)))
00430       {
00431         ptr_ = static_cast<T*>(other.ptr_);
00432         ConnectListener();
00433       }
00434     }
00435 
00437 
00440     template <typename O>
00441     ObjectWeakPtr(const ObjectPtr<O> &other)
00442       : ptr_(nullptr)
00443     {
00444       if (other.ptr_ &&
00445           (other.ptr_->Type().IsDerivedFromType(T::StaticObjectType)))
00446       {
00447         ptr_ = static_cast<T*>(other.ptr_);
00448         ConnectListener();
00449       }
00450     }
00451 
00453 
00456     ObjectWeakPtr& operator = (ObjectWeakPtr<T> const& other)
00457     {
00458       Disconnect();
00459       ptr_ = other.ptr_;
00460       ConnectListener();
00461       return *this;
00462     }
00463 
00464     // Warning: We are not sure that other.ptr_ is valid.
00465     // Warning: Cannot call other.ptr_->Type().IsDerivedFromType (T::StaticObjectType)
00467 
00470     template <typename O>
00471     ObjectWeakPtr &operator = (const ObjectWeakPtr<O>& other)
00472     {
00473       Disconnect();
00474       if (other.ptr_ &&
00475           other.ptr_->Type().IsDerivedFromType(T::StaticObjectType))
00476       {
00477         ptr_ = static_cast<T*>(other.ptr_);
00478         ConnectListener();
00479       }
00480       return *this;
00481     }
00482 
00484 
00487     template <typename O>
00488     ObjectWeakPtr &operator = (const ObjectPtr<O>& other)
00489     {
00490       Disconnect();
00491       if (other.ptr_ &&
00492           other.ptr_->Type().IsDerivedFromType(T::StaticObjectType))
00493       {
00494         ptr_ = static_cast<T*>(other.ptr_);
00495         ConnectListener();
00496       }
00497       return *this;
00498     }
00499 
00501 
00507     ObjectWeakPtr& operator = (T* ptr)
00508     {
00509       Disconnect();
00510       ptr_ = ptr;
00511       ConnectListener();
00512       return *this;
00513     }
00514 
00515     template <typename O>
00516     ObjectWeakPtr &operator = (O* ptr)
00517     {
00518       Disconnect();
00519       if (ptr &&
00520           ptr->Type().IsDerivedFromType(T::StaticObjectType))
00521       {
00522         ptr_ = static_cast<T*>(ptr);
00523         ConnectListener();
00524       }
00525       return *this;
00526     }
00527 
00528     ~ObjectWeakPtr()
00529     {
00530       Disconnect();
00531     }
00532 
00533     T& operator* () const
00534     {
00535       nuxAssert (ptr_ != 0);
00536       return *(const_cast<T*>(ptr_));
00537     }
00538 
00539     T* operator -> () const
00540     {
00541       nuxAssert (ptr_ != 0);
00542       return const_cast<T*>(ptr_);
00543     }
00544 
00545     bool operator < (T *ptr) const
00546     {
00547       return (ptr_ < ptr);
00548     }
00549 
00550     bool operator > (T *ptr) const
00551     {
00552       return (ptr_ > ptr);
00553     }
00554 
00555     bool operator < (ObjectWeakPtr<T> other) const
00556     {
00557       return (ptr_ < other.ptr_);
00558     }
00559 
00560     bool operator > (ObjectWeakPtr<T> other) const
00561     {
00562       return (ptr_ > other.ptr_);
00563     }
00564 
00565     template <typename U>
00566     bool operator != (U other) const
00567     {
00568       return !(*this == other);
00569     }
00570     bool operator == (T *ptr) const
00571     {
00572       return ptr_ == ptr;
00573     }
00574 
00575     template<typename U>
00576     bool operator == (U *ptr) const
00577     {
00578       if (ptr && (!ptr->Type().IsDerivedFromType (T::StaticObjectType) ) )
00579         return false;
00580 
00581       return ptr_ == static_cast<T*>(ptr);
00582     }
00583 
00588     template<typename U>
00589     bool operator == (const ObjectWeakPtr<U>& other) const
00590     {
00591       if (other.ptr_ && (!other.ptr_->Type().IsDerivedFromType (T::StaticObjectType) ) )
00592         return false;
00593 
00594       return ptr_ == static_cast<T*>(other.ptr_);
00595     }
00596 
00601     template<typename U>
00602     bool operator == (const ObjectPtr<U>& other) const
00603     {
00604       if (other.ptr_ && (!other.ptr_->Type().IsDerivedFromType (T::StaticObjectType) ) )
00605         return false;
00606 
00607       return ptr_ == static_cast<T*>(other.ptr_);
00608     }
00609 
00611 
00614     bool operator() () const
00615     {
00616       return bool(ptr_);
00617     }
00618 
00620 
00623     bool IsValid() const
00624     {
00625       return bool(ptr_);
00626     }
00627 
00629 
00632     bool IsNull() const
00633     {
00634       return !IsValid();
00635     }
00636 
00638 
00647     bool Release()
00648     {
00649         Disconnect();
00650         ptr_ = nullptr;
00651         return false;
00652     }
00653 
00655 
00659     const T* GetPointer () const
00660     {
00661       return ptr_;
00662     }
00663 
00665 
00669     T* GetPointer()
00670     {
00671       return ptr_;
00672     }
00673 
00674   private:
00675     void Disconnect()
00676     {
00677       if (destroy_listener_.connected())
00678         destroy_listener_.disconnect();
00679     }
00680 
00681     void ConnectListener()
00682     {
00683       if (ptr_)
00684       {
00685         auto slot = sigc::mem_fun(this, &ObjectWeakPtr<T>::TargetDestroyed);
00686         destroy_listener_ = ptr_->object_destroyed.connect(slot);
00687       }
00688     }
00689 
00690     void TargetDestroyed(Object* ptr)
00691     {
00692         ptr_ = nullptr;
00693         // rese the connetion too
00694         destroy_listener_ = sigc::connection();
00695     }
00696 
00697     T* ptr_;
00698     sigc::connection destroy_listener_;
00699 
00700     template <typename O>
00701     friend class ObjectWeakPtr;
00702 
00703     template<typename U>
00704     friend bool operator == (U *, const ObjectWeakPtr<U>& a);
00705 
00706     template<typename U>
00707     friend bool operator != (U *, const ObjectWeakPtr<U>& a);
00708 
00709     template <typename U, typename F>
00710     friend ObjectWeakPtr<U> staticCast (const ObjectWeakPtr<F>& from);
00711 
00712     template <typename U, typename F>
00713     friend ObjectWeakPtr<U> constCast (const ObjectWeakPtr<F>& from);
00714 
00715     template <typename U, typename F>
00716     friend ObjectWeakPtr<U> dynamicCast (const ObjectWeakPtr<F>& from);
00717 
00718     template <typename U, typename F>
00719     friend ObjectWeakPtr<U> checkedCast (const ObjectWeakPtr<F>& from);
00720 
00721     template <typename U, typename F>
00722     friend ObjectWeakPtr<U> queryCast (const ObjectWeakPtr<F>& from);
00723   };
00724 
00726 // globals
00727 
00728 
00729   template<typename T>
00730   inline bool operator == (T *ptr, const ObjectPtr<T>& a)
00731   {
00732     return a.ptr_ == ptr;
00733   }
00734 
00735   template<typename T>
00736   inline bool operator != (T *ptr, const ObjectPtr<T>& a)
00737   {
00738     return a.ptr_ != ptr;
00739   }
00740 
00741   template<typename T>
00742   inline bool operator == (T *ptr, const ObjectWeakPtr<T>& a)
00743   {
00744     return a.ptr_ == ptr;
00745   }
00746 
00747   template<typename T>
00748   inline bool operator != (T *ptr, const ObjectWeakPtr<T>& a)
00749   {
00750     return a.ptr_ != ptr;
00751   }
00752 
00753 }
00754 
00755 #endif
00756 
00757 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends