/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #ifndef __NSHARED_PTR__ #define __NSHARED_PTR__ #include "thread/atomic_value.h" namespace GS { /// Weak reference to a shared object. class WeakRef { friend class SharedObject; bool is_valid; Threading::Atomic32 refc; WeakRef() : is_valid(true) {} public: bool IsValid() const { return is_valid; } int GetRefCount() const { return refc.Get(); } void AddRef() { refc.Inc(); } void RemoveRef() { if ((refc.Dec() == 0) && !is_valid) delete this; } }; /*! @short Reference counted object. @author Emmanuel Julien (ejulien@gsworks.fr) */ class SharedObject { Threading::Atomic32 refc; WeakRef *weak_ref; protected: virtual ~SharedObject() { if (weak_ref) { if (weak_ref->refc.Get() == 0) delete weak_ref; else weak_ref->is_valid = false; } } public: WeakRef *GetWeakRef() { if (!weak_ref) weak_ref = new WeakRef; // TODO have a specialized, fixed pool allocator for these. return weak_ref; } int GetRefCount() const { return refc.Get(); } void AddRef() { refc.Inc(); } void RemoveRef() { if (refc.Dec() == 0) { if (weak_ref) weak_ref->is_valid = false; delete this; } } SharedObject() : weak_ref(0) {} }; /*! @short Strong smart pointer to a reference counted object. @author Emmanuel Julien (ejulien@gsworks.fr) */ template class SharedPtr { T *rc_o; public: inline operator T *() const { return rc_o; } inline T *c_ptr() const { return rc_o; } inline bool IsNull() const { return rc_o ? false : true; } inline bool IsValid() const { return rc_o ? true : false; } void Init() { if (rc_o) rc_o->AddRef(); } inline bool operator == (const T *p) const { return rc_o == p; } inline bool operator != (const T *p) const { return rc_o != p; } inline bool operator == (T *p) const { return rc_o == p; } inline bool operator != (T *p) const { return rc_o != p; } inline bool operator == (const SharedPtr &p) const { return rc_o == p.rc_o; } inline bool operator != (const SharedPtr &p) const { return rc_o != p.rc_o; } T *operator = (T *p) { if (rc_o != p) { if (rc_o) rc_o->RemoveRef(); rc_o = p; Init(); } return p; } SharedPtr &operator = (const SharedPtr &p) { *this = p.c_ptr(); return *this; } inline T *operator -> () const { return rc_o; } inline T &operator * () const { return *rc_o; } explicit SharedPtr(T *p) : rc_o(p) { Init(); } SharedPtr(const SharedPtr &p) : rc_o(p.rc_o) { Init(); } SharedPtr() : rc_o(0) {} ~SharedPtr() { if (rc_o) rc_o->RemoveRef(); } }; } // GS #endif // __NSHARED_PTR__