151 lines
2.8 KiB
C++
151 lines
2.8 KiB
C++
/* -----------------------------------------------------------------------------
|
|
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 T> 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 <T> &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__
|