Horde3D http://horde3d.org/forums/ |
|
loose_ptr<T> code http://horde3d.org/forums/viewtopic.php?f=5&t=1591 |
Page 1 of 1 |
Author: | AcidFaucet [ 08.11.2011, 01:37 ] |
Post subject: | loose_ptr<T> code |
In my opinion weak_ptr is one of the best parts about shared_ptr. I didn't want to start adding shared_ptr's in but didn't want to have some insane management going on either so I whipped together this invasive guy so I could get loose_ptr<T> from anyone who inherits from enable_loose_ptr. Then my manager just had to to periodically prune the ones that had gone bad while it was checking to see if it still cared about the good ones. So I thought I'd share. If you read up on weak_ptr and enabled_shared_from_this<T> you should be able to get how it works pretty easily (unlike weak_ptr this will work with variables on the stack too). Code: #pragma once
// Copyright (C) 2011 - Jonathan Sandusky // MIT License - read it here http://www.opensource.org/licenses/mit-license.php // // an invasive pointer that gets reset when the target object is destroyed // (polymorphism is not supported here) // template<class TYPE> class loose_ptr { loose_ptr<TYPE>& operator=(int); // prevent "obj=0;" because it doesn't work right private: TYPE* ptr_; loose_ptr* next_; public: // default constructor loose_ptr() : ptr_(0), next_(0) {} // construct from dumb pointer loose_ptr(TYPE* p) : ptr_(0), next_(0) {set(p);} // construct from derived class dumb pointer template<class T> loose_ptr(T* p) : ptr_(0), next_(0) {set(p);} // construct from smart_ptr, shared_ptr, etc. template<class T> loose_ptr(const T& t) : ptr_(0), next_(0) {set(t.get());} // copy constructor (specialization of above) loose_ptr(const loose_ptr& rhs) : ptr_(0), next_(0) {set(rhs.ptr_);} // destructor ~loose_ptr() {set(0);} TYPE* ptr() const {return ptr_;} TYPE* get() const {return ptr_;} TYPE* operator->() const {assert(ptr_); return ptr_;} TYPE& operator*() const {assert(ptr_); return *ptr_;} bool operator==(TYPE* p) const {return p == ptr_;} bool operator!=(TYPE* p) const {return p != ptr_;} bool expired() const {return !ptr_;} class incomplete_class; operator const incomplete_class*() const {return (const incomplete_class*)ptr_;} // assign from dumb pointer loose_ptr& operator=(TYPE* p) {set(p); return *this;} // assign from smart_ptr, shared_ptr, etc. template<class T> loose_ptr& operator=(const T& t) {set(t.get()); return *this;} // assignment operator (specialization of above) loose_ptr& operator=(const loose_ptr& rhs) {set(rhs.ptr_); return *this;} void reset(TYPE* aPtr = 0) {set(aPtr);} void set(TYPE* aPtr) { if (aPtr != ptr_) { const enable_loose_ptr<TYPE>* ptr = ptr_; if (ptr != 0) { if (ptr->loose_ptr_head_ == this) { ptr->loose_ptr_head_ = next_; } else { loose_ptr* prev = 0; for (loose_ptr* p = ptr->loose_ptr_head_; p && p != this; prev = p, p = p->next_); assert(prev && prev->next_ == this); if (prev && prev->next_ == this) prev->next_ = next_; } next_ = 0; } ptr = ptr_ = aPtr; if (ptr_) { next_ = ptr->loose_ptr_head_; ptr->loose_ptr_head_ = this; } } } }; // // required base class for objects that can have loose pointers to them // template<class TYPE> class enable_loose_ptr { public: // default constructor enable_loose_ptr() : loose_ptr_head_(0) { } // copy constructor enable_loose_ptr(const enable_loose_ptr&) : loose_ptr_head_(0) { } // destructor ~enable_loose_ptr() { while (loose_ptr_head_) loose_ptr_head_->set(0); } // assignment operator enable_loose_ptr& operator=(const enable_loose_ptr&) { } private: friend class loose_ptr<TYPE>; mutable loose_ptr<TYPE>* loose_ptr_head_; }; |
Page 1 of 1 | All times are UTC + 1 hour |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |