/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


#ifndef	__NWEAK_PTR__
#define __NWEAK_PTR__


		#include "memory/nshared_ptr.h"


namespace GS {

/*!
	@short	Weak pointer to a reference counted object.
	@author	Emmanuel Julien (ejulien@gsworks.fr)
*/
template <class T> class WeakPtr
{
private:

		T			*rc_o;
		WeakRef		*wref;

public:

		T			*c_ptr() const { return wref && wref->IsValid() ? rc_o : 0; }

		bool		IsValid() const { return wref && wref->IsValid() ? true : false; }
		bool		IsNull() const { return !IsValid(); }

		/// Lock pointed object to a strong pointer.
		bool		Lock(SharedPtr <T> &p)
		{
			if	(IsNull())
				return false;
			p = rc_o;
			return true;
		}
		SharedPtr <T> Lock() const { return SharedPtr <T> (IsValid() ? rc_o : 0); }

		void		Init()
		{
			if	(!rc_o)
				wref = 0;
			else
			{
				wref = rc_o->GetWeakRef();
				wref->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 WeakPtr &p) const
		{	return rc_o == p.rc_o;	}
inline	bool		operator != (const WeakPtr &p) const
		{	return rc_o != p.rc_o;	}

		WeakPtr <T> &operator = (const WeakPtr &p)
		{
			if	(rc_o != p.rc_o)
			{
				WeakRef *old_wref = wref;

				rc_o = p.rc_o;
				Init();

				if	(old_wref)
					old_wref->RemoveRef();
			}
			return *this;
		}
inline	T			*operator -> () const
		{	return rc_o;	}
inline	T			&operator * () const
		{	return *rc_o;	}

		WeakPtr(T *p = 0) : rc_o(p) { Init(); }
		WeakPtr(const WeakPtr &p) : rc_o(p.rc_o) { Init(); }
		WeakPtr(const SharedPtr <T> &p) : rc_o(p.c_ptr()) { Init(); }
		~WeakPtr()
		{
			if	(wref)
				wref->RemoveRef();
		}
};

} // GS


#endif	// __NWEAK_PTR__
