1/*
2 * Copyright 2004-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef _REFERENCEABLE_H
6#define _REFERENCEABLE_H
7
8
9#include <SupportDefs.h>
10
11
12// #pragma mark - BReferenceable
13
14
15class BReferenceable {
16public:
17								BReferenceable();
18	virtual						~BReferenceable();
19
20								// acquire and release return
21								// the previous ref count
22			int32				AcquireReference();
23			int32				ReleaseReference();
24
25			int32				CountReferences() const
26									{ return fReferenceCount; }
27
28protected:
29	virtual	void				FirstReferenceAcquired();
30	virtual	void				LastReferenceReleased();
31
32protected:
33			int32				fReferenceCount;
34};
35
36
37// #pragma mark - BReference
38
39
40template<typename Type = BReferenceable>
41class BReference {
42public:
43	BReference()
44		:
45		fObject(NULL)
46	{
47	}
48
49	BReference(Type* object, bool alreadyHasReference = false)
50		:
51		fObject(NULL)
52	{
53		SetTo(object, alreadyHasReference);
54	}
55
56	BReference(const BReference<Type>& other)
57		:
58		fObject(NULL)
59	{
60		SetTo(other.Get());
61	}
62
63	template<typename OtherType>
64	BReference(const BReference<OtherType>& other)
65		:
66		fObject(NULL)
67	{
68		SetTo(other.Get());
69	}
70
71	~BReference()
72	{
73		Unset();
74	}
75
76	void SetTo(Type* object, bool alreadyHasReference = false)
77	{
78		if (object != NULL && !alreadyHasReference)
79			object->AcquireReference();
80
81		Unset();
82
83		fObject = object;
84	}
85
86	void Unset()
87	{
88		if (fObject) {
89			fObject->ReleaseReference();
90			fObject = NULL;
91		}
92	}
93
94	Type* Get() const
95	{
96		return fObject;
97	}
98
99	Type* Detach()
100	{
101		Type* object = fObject;
102		fObject = NULL;
103		return object;
104	}
105
106	Type& operator*() const
107	{
108		return *fObject;
109	}
110
111	Type* operator->() const
112	{
113		return fObject;
114	}
115
116	operator Type*() const
117	{
118		return fObject;
119	}
120
121	BReference& operator=(const BReference<Type>& other)
122	{
123		SetTo(other.fObject);
124		return *this;
125	}
126
127	BReference& operator=(Type* other)
128	{
129		SetTo(other);
130		return *this;
131	}
132
133	template<typename OtherType>
134	BReference& operator=(const BReference<OtherType>& other)
135	{
136		SetTo(other.Get());
137		return *this;
138	}
139
140	bool operator==(const BReference<Type>& other) const
141	{
142		return fObject == other.fObject;
143	}
144
145	bool operator==(const Type* other) const
146	{
147		return fObject == other;
148	}
149
150	bool operator!=(const BReference<Type>& other) const
151	{
152		return fObject != other.fObject;
153	}
154
155	bool operator!=(const Type* other) const
156	{
157		return fObject != other;
158	}
159
160private:
161	Type*	fObject;
162};
163
164
165// #pragma mark - BReference<const>
166
167
168template<typename Type>
169class BReference<const Type> {
170public:
171	BReference(Type* object, bool alreadyHasReference = false)
172		:
173		fReference(object, alreadyHasReference)
174	{
175	}
176
177	BReference(const BReference<const Type>& other)
178		:
179		fReference(const_cast<Type*>(other.Get()))
180	{
181	}
182
183	template<typename OtherType>
184	BReference(const BReference<OtherType>& other)
185		:
186		fReference(other.Get())
187	{
188	}
189
190	void SetTo(Type* object, bool alreadyHasReference = false)
191	{
192		fReference.SetTo(object, alreadyHasReference);
193	}
194
195	void Unset()
196	{
197		fReference.Unset();
198	}
199
200	const Type* Get() const
201	{
202		return fReference.Get();
203	}
204
205	const Type* Detach()
206	{
207		return fReference.Detach();
208	}
209
210	const Type& operator*() const
211	{
212		return *fReference;
213	}
214
215	const Type* operator->() const
216	{
217		return fReference.Get();
218	}
219
220	operator const Type*() const
221	{
222		return fReference.Get();
223	}
224
225	BReference& operator=(const BReference<const Type>& other)
226	{
227		fReference = other.fReference;
228	}
229
230	BReference& operator=(Type* other)
231	{
232		fReference = other;
233	}
234
235	template<typename OtherType>
236	BReference& operator=(const BReference<OtherType>& other)
237	{
238		fReference = other.Get();
239	}
240
241	bool operator==(const BReference<const Type>& other) const
242	{
243		return fReference == other.Get();
244	}
245
246	bool operator==(const Type* other) const
247	{
248		return fReference == other;
249	}
250
251	bool operator!=(const BReference<const Type>& other) const
252	{
253		return fReference != other.Get();
254	}
255
256	bool operator!=(const Type* other) const
257	{
258		return fReference != other;
259	}
260
261private:
262	BReference<Type> fReference;
263};
264
265
266#endif	// _REFERENCEABLE_H
267