12851dbadSAxel Dörfler/*
2756b64fdSIngo Weinhold * Copyright 2004-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3757bc7b9SIngo Weinhold * Distributed under the terms of the MIT License.
4757bc7b9SIngo Weinhold */
52851dbadSAxel Dörfler#ifndef _REFERENCEABLE_H
62851dbadSAxel Dörfler#define _REFERENCEABLE_H
747e01f50SIngo Weinhold
847e01f50SIngo Weinhold
947e01f50SIngo Weinhold#include <SupportDefs.h>
1047e01f50SIngo Weinhold
112851dbadSAxel Dörfler
12756b64fdSIngo Weinhold// #pragma mark - BReferenceable
13756b64fdSIngo Weinhold
14756b64fdSIngo Weinhold
154736b6b9SIngo Weinholdclass BReferenceable {
1647e01f50SIngo Weinholdpublic:
17756b64fdSIngo Weinhold								BReferenceable();
184736b6b9SIngo Weinhold	virtual						~BReferenceable();
1947e01f50SIngo Weinhold
208c3c1172SRene Gollent								// acquire and release return
218c3c1172SRene Gollent								// the previous ref count
22a99d0dd7SRene Gollent			int32				AcquireReference();
238c3c1172SRene Gollent			int32				ReleaseReference();
2447e01f50SIngo Weinhold
252851dbadSAxel Dörfler			int32				CountReferences() const
262851dbadSAxel Dörfler									{ return fReferenceCount; }
2747e01f50SIngo Weinhold
287aa7cb4bSIngo Weinholdprotected:
297aa7cb4bSIngo Weinhold	virtual	void				FirstReferenceAcquired();
307aa7cb4bSIngo Weinhold	virtual	void				LastReferenceReleased();
317aa7cb4bSIngo Weinhold
3247e01f50SIngo Weinholdprotected:
33077c84ebSPawel Dziepak			int32				fReferenceCount;
3447e01f50SIngo Weinhold};
3547e01f50SIngo Weinhold
367aa7cb4bSIngo Weinhold
37756b64fdSIngo Weinhold// #pragma mark - BReference
387aa7cb4bSIngo Weinhold
397aa7cb4bSIngo Weinhold
4049e8a3c6SAdrien Destuguestemplate<typename Type = BReferenceable>
414736b6b9SIngo Weinholdclass BReference {
424736b6b9SIngo Weinholdpublic:
434736b6b9SIngo Weinhold	BReference()
4432951c4eSczeidler		:
4532951c4eSczeidler		fObject(NULL)
464736b6b9SIngo Weinhold	{
474736b6b9SIngo Weinhold	}
484736b6b9SIngo Weinhold
494736b6b9SIngo Weinhold	BReference(Type* object, bool alreadyHasReference = false)
5032951c4eSczeidler		:
5132951c4eSczeidler		fObject(NULL)
524736b6b9SIngo Weinhold	{
534736b6b9SIngo Weinhold		SetTo(object, alreadyHasReference);
544736b6b9SIngo Weinhold	}
554736b6b9SIngo Weinhold
564736b6b9SIngo Weinhold	BReference(const BReference<Type>& other)
5732951c4eSczeidler		:
5832951c4eSczeidler		fObject(NULL)
594736b6b9SIngo Weinhold	{
60e9b82428SAdrien Destugues		SetTo(other.Get());
614736b6b9SIngo Weinhold	}
624736b6b9SIngo Weinhold
63b5c5640eSczeidler	template<typename OtherType>
6432951c4eSczeidler	BReference(const BReference<OtherType>& other)
6532951c4eSczeidler		:
6632951c4eSczeidler		fObject(NULL)
6732951c4eSczeidler	{
6832951c4eSczeidler		SetTo(other.Get());
6932951c4eSczeidler	}
7032951c4eSczeidler
714736b6b9SIngo Weinhold	~BReference()
724736b6b9SIngo Weinhold	{
734736b6b9SIngo Weinhold		Unset();
744736b6b9SIngo Weinhold	}
754736b6b9SIngo Weinhold
764736b6b9SIngo Weinhold	void SetTo(Type* object, bool alreadyHasReference = false)
774736b6b9SIngo Weinhold	{
784736b6b9SIngo Weinhold		if (object != NULL && !alreadyHasReference)
79755a1de8SAxel Dörfler			object->AcquireReference();
804736b6b9SIngo Weinhold
814736b6b9SIngo Weinhold		Unset();
824736b6b9SIngo Weinhold
834736b6b9SIngo Weinhold		fObject = object;
844736b6b9SIngo Weinhold	}
854736b6b9SIngo Weinhold
864736b6b9SIngo Weinhold	void Unset()
874736b6b9SIngo Weinhold	{
884736b6b9SIngo Weinhold		if (fObject) {
89755a1de8SAxel Dörfler			fObject->ReleaseReference();
904736b6b9SIngo Weinhold			fObject = NULL;
914736b6b9SIngo Weinhold		}
924736b6b9SIngo Weinhold	}
934736b6b9SIngo Weinhold
9449e8a3c6SAdrien Destugues	Type* Get() const
954736b6b9SIngo Weinhold	{
964736b6b9SIngo Weinhold		return fObject;
974736b6b9SIngo Weinhold	}
984736b6b9SIngo Weinhold
9949e8a3c6SAdrien Destugues	Type* Detach()
1004736b6b9SIngo Weinhold	{
1014736b6b9SIngo Weinhold		Type* object = fObject;
1024736b6b9SIngo Weinhold		fObject = NULL;
1034736b6b9SIngo Weinhold		return object;
1044736b6b9SIngo Weinhold	}
1054736b6b9SIngo Weinhold
10649e8a3c6SAdrien Destugues	Type& operator*() const
1074736b6b9SIngo Weinhold	{
1084736b6b9SIngo Weinhold		return *fObject;
1094736b6b9SIngo Weinhold	}
1104736b6b9SIngo Weinhold
11149e8a3c6SAdrien Destugues	Type* operator->() const
1124736b6b9SIngo Weinhold	{
1134736b6b9SIngo Weinhold		return fObject;
1144736b6b9SIngo Weinhold	}
1154736b6b9SIngo Weinhold
11649e8a3c6SAdrien Destugues	operator Type*() const
117a28bf6c7SClemens Zeidler	{
118a28bf6c7SClemens Zeidler		return fObject;
119a28bf6c7SClemens Zeidler	}
120a28bf6c7SClemens Zeidler
12149e8a3c6SAdrien Destugues	BReference& operator=(const BReference<Type>& other)
1224736b6b9SIngo Weinhold	{
1234736b6b9SIngo Weinhold		SetTo(other.fObject);
1244736b6b9SIngo Weinhold		return *this;
1254736b6b9SIngo Weinhold	}
1264736b6b9SIngo Weinhold
12732951c4eSczeidler	BReference& operator=(Type* other)
12832951c4eSczeidler	{
12932951c4eSczeidler		SetTo(other);
13032951c4eSczeidler		return *this;
13132951c4eSczeidler	}
13232951c4eSczeidler
13349e8a3c6SAdrien Destugues	template<typename OtherType>
13449e8a3c6SAdrien Destugues	BReference& operator=(const BReference<OtherType>& other)
13532951c4eSczeidler	{
13632951c4eSczeidler		SetTo(other.Get());
13732951c4eSczeidler		return *this;
13832951c4eSczeidler	}
13932951c4eSczeidler
14049e8a3c6SAdrien Destugues	bool operator==(const BReference<Type>& other) const
1414736b6b9SIngo Weinhold	{
1425b9400a2Sczeidler		return fObject == other.fObject;
1434736b6b9SIngo Weinhold	}
1444736b6b9SIngo Weinhold
145b9b8b20fSczeidler	bool operator==(const Type* other) const
146b9b8b20fSczeidler	{
1475b9400a2Sczeidler		return fObject == other;
148b9b8b20fSczeidler	}
149b9b8b20fSczeidler
15049e8a3c6SAdrien Destugues	bool operator!=(const BReference<Type>& other) const
1514736b6b9SIngo Weinhold	{
1525b9400a2Sczeidler		return fObject != other.fObject;
1534736b6b9SIngo Weinhold	}
1544736b6b9SIngo Weinhold
155b9b8b20fSczeidler	bool operator!=(const Type* other) const
156b9b8b20fSczeidler	{
1575b9400a2Sczeidler		return fObject != other;
158b9b8b20fSczeidler	}
159b9b8b20fSczeidler
1604736b6b9SIngo Weinholdprivate:
1614736b6b9SIngo Weinhold	Type*	fObject;
1624736b6b9SIngo Weinhold};
1634736b6b9SIngo Weinhold
1644736b6b9SIngo Weinhold
16549e8a3c6SAdrien Destugues// #pragma mark - BReference<const>
166e9b82428SAdrien Destugues
167e9b82428SAdrien Destugues
16849e8a3c6SAdrien Destuguestemplate<typename Type>
16949e8a3c6SAdrien Destuguesclass BReference<const Type> {
170e9b82428SAdrien Destuguespublic:
17149e8a3c6SAdrien Destugues	BReference(Type* object, bool alreadyHasReference = false)
172e9b82428SAdrien Destugues		:
17349e8a3c6SAdrien Destugues		fReference(object, alreadyHasReference)
174e9b82428SAdrien Destugues	{
175e9b82428SAdrien Destugues	}
176e9b82428SAdrien Destugues
17749e8a3c6SAdrien Destugues	BReference(const BReference<const Type>& other)
178e9b82428SAdrien Destugues		:
179404cb7e3SAdrien Destugues		fReference(const_cast<Type*>(other.Get()))
180e9b82428SAdrien Destugues	{
181e9b82428SAdrien Destugues	}
182e9b82428SAdrien Destugues
18349e8a3c6SAdrien Destugues	template<typename OtherType>
18449e8a3c6SAdrien Destugues	BReference(const BReference<OtherType>& other)
185e9b82428SAdrien Destugues		:
18649e8a3c6SAdrien Destugues		fReference(other.Get())
187e9b82428SAdrien Destugues	{
188e9b82428SAdrien Destugues	}
189e9b82428SAdrien Destugues
19049e8a3c6SAdrien Destugues	void SetTo(Type* object, bool alreadyHasReference = false)
191e9b82428SAdrien Destugues	{
19249e8a3c6SAdrien Destugues		fReference.SetTo(object, alreadyHasReference);
19349e8a3c6SAdrien Destugues	}
19449e8a3c6SAdrien Destugues
19549e8a3c6SAdrien Destugues	void Unset()
19649e8a3c6SAdrien Destugues	{
19749e8a3c6SAdrien Destugues		fReference.Unset();
198e9b82428SAdrien Destugues	}
199e9b82428SAdrien Destugues
20049e8a3c6SAdrien Destugues	const Type* Get() const
20149e8a3c6SAdrien Destugues	{
20249e8a3c6SAdrien Destugues		return fReference.Get();
20349e8a3c6SAdrien Destugues	}
20449e8a3c6SAdrien Destugues
20549e8a3c6SAdrien Destugues	const Type* Detach()
20649e8a3c6SAdrien Destugues	{
20749e8a3c6SAdrien Destugues		return fReference.Detach();
20849e8a3c6SAdrien Destugues	}
20949e8a3c6SAdrien Destugues
21049e8a3c6SAdrien Destugues	const Type& operator*() const
21149e8a3c6SAdrien Destugues	{
21249e8a3c6SAdrien Destugues		return *fReference;
21349e8a3c6SAdrien Destugues	}
21449e8a3c6SAdrien Destugues
21549e8a3c6SAdrien Destugues	const Type* operator->() const
21649e8a3c6SAdrien Destugues	{
21749e8a3c6SAdrien Destugues		return fReference.Get();
21849e8a3c6SAdrien Destugues	}
21949e8a3c6SAdrien Destugues
22049e8a3c6SAdrien Destugues	operator const Type*() const
22149e8a3c6SAdrien Destugues	{
22249e8a3c6SAdrien Destugues		return fReference.Get();
22349e8a3c6SAdrien Destugues	}
22449e8a3c6SAdrien Destugues
22549e8a3c6SAdrien Destugues	BReference& operator=(const BReference<const Type>& other)
22649e8a3c6SAdrien Destugues	{
22749e8a3c6SAdrien Destugues		fReference = other.fReference;
22849e8a3c6SAdrien Destugues	}
22949e8a3c6SAdrien Destugues
23049e8a3c6SAdrien Destugues	BReference& operator=(Type* other)
23149e8a3c6SAdrien Destugues	{
23249e8a3c6SAdrien Destugues		fReference = other;
23349e8a3c6SAdrien Destugues	}
23449e8a3c6SAdrien Destugues
23549e8a3c6SAdrien Destugues	template<typename OtherType>
23649e8a3c6SAdrien Destugues	BReference& operator=(const BReference<OtherType>& other)
23749e8a3c6SAdrien Destugues	{
23849e8a3c6SAdrien Destugues		fReference = other.Get();
23949e8a3c6SAdrien Destugues	}
24049e8a3c6SAdrien Destugues
24149e8a3c6SAdrien Destugues	bool operator==(const BReference<const Type>& other) const
24249e8a3c6SAdrien Destugues	{
24349e8a3c6SAdrien Destugues		return fReference == other.Get();
24449e8a3c6SAdrien Destugues	}
24549e8a3c6SAdrien Destugues
24649e8a3c6SAdrien Destugues	bool operator==(const Type* other) const
24749e8a3c6SAdrien Destugues	{
24849e8a3c6SAdrien Destugues		return fReference == other;
24949e8a3c6SAdrien Destugues	}
25049e8a3c6SAdrien Destugues
25149e8a3c6SAdrien Destugues	bool operator!=(const BReference<const Type>& other) const
25249e8a3c6SAdrien Destugues	{
25349e8a3c6SAdrien Destugues		return fReference != other.Get();
25449e8a3c6SAdrien Destugues	}
25549e8a3c6SAdrien Destugues
25649e8a3c6SAdrien Destugues	bool operator!=(const Type* other) const
25749e8a3c6SAdrien Destugues	{
25849e8a3c6SAdrien Destugues		return fReference != other;
25949e8a3c6SAdrien Destugues	}
26049e8a3c6SAdrien Destugues
26149e8a3c6SAdrien Destuguesprivate:
26249e8a3c6SAdrien Destugues	BReference<Type> fReference;
263e9b82428SAdrien Destugues};
264e9b82428SAdrien Destugues
265e9b82428SAdrien Destugues
2662851dbadSAxel Dörfler#endif	// _REFERENCEABLE_H
267