IntrusivePtr.h

Go to the documentation of this file.
00001 #ifndef IntrusivePtr_HEADER
00002 #define IntrusivePtr_HEADER
00003 
00004 /***************************************************************************
00005  * Benoit Hudson (C) 2007.
00006  ***************************************************************************/
00007 
00008 namespace hudson {
00009 
00010 /***************************************************************************
00011  * An implementation of a boost-like intrusive shared pointer.
00012  *
00013  * It's not clear how the boost intrusive_ptr could possibly work holding
00014  * templated types.  Here I redo it in a more limited setting.
00015  *
00016  * Standard usage would be:
00017  * class Foo  {
00018  *   int refcount;
00019  *   friend class hudson::IntrusivePtr<Foo>;
00020  *   static void add_ref(Foo *f) { f->refcount++; }
00021  *   static void release(Foo *f) { f->refcount--; if (f->refcount == 0) { delete f; } }
00022  *   public:
00023  *   Foo(): refcount(0) { }
00024  * };
00025  * class Bar  {
00026  *   hudson::IntrusivePtr<Foo> f;
00027  * };
00028  *
00029  * If you don't have access to write the add_ref/release functions into the
00030  * object (or if T is a base type), specify a different class that has those
00031  * two static functions.
00032  ***************************************************************************/
00033 template <class T, class AddRelease=T>
00034 class IntrusivePtr {
00035   T *ptr_;
00036 
00037   void addref() {
00038     if (ptr_) {
00039       AddRelease::add_ref(ptr_);
00040     }
00041   }
00042   void delref() {
00043     if (ptr_) {
00044       AddRelease::release(ptr_);
00045     }
00046   }
00047 
00048   public:
00049   IntrusivePtr(): ptr_(0) { }
00050   IntrusivePtr(T *p): ptr_(p) { addref(); }
00051   IntrusivePtr(const IntrusivePtr& other): ptr_(other.get()) { addref(); }
00052   ~IntrusivePtr() { delref(); }
00053 
00054   IntrusivePtr& operator= (T *p) {
00055     /* don't delref/addref if we're reassigning (we might hold the only reference!). */
00056     if (p == ptr_) { return *this; }
00057     delref();
00058     ptr_ = p;
00059     addref();
00060     return *this;
00061   }
00062   IntrusivePtr& operator= (const IntrusivePtr& other) {
00063     return this->operator= (other.get());
00064   }
00065 
00066   T *get() const {
00067     return ptr_;
00068   }
00069 
00070   T& operator*() const {
00071     return *ptr_;
00072   }
00073 
00074   T *operator->() const {
00075     return ptr_;
00076   }
00077 
00078   operator bool() const {
00079     return ptr_ != 0;
00080   }
00081 
00082   bool operator== (const T* p) const { return ptr_ == p; }
00083   bool operator!= (const T* p) const { return ptr_ != p; }
00084 
00085   bool operator== (const IntrusivePtr& p) const { return ptr_ == p.get(); }
00086   bool operator!= (const IntrusivePtr& p) const { return ptr_ != p.get(); }
00087 };
00088 
00089 } // namespace hudson
00090 
00091 #endif

Generated on Thu Mar 27 19:04:14 2008 by  doxygen 1.4.6