nux-1.14.0
|
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