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	bool IsSet() const
95	{
96		return fObject != NULL;
97	}
98
99	Type* Get() const
100	{
101		return fObject;
102	}
103
104	Type* Detach()
105	{
106		Type* object = fObject;
107		fObject = NULL;
108		return object;
109	}
110
111	Type& operator*() const
112	{
113		return *fObject;
114	}
115
116	Type* operator->() const
117	{
118		return fObject;
119	}
120
121	operator Type*() const
122	{
123		return fObject;
124	}
125
126	BReference& operator=(const BReference<Type>& other)
127	{
128		SetTo(other.fObject);
129		return *this;
130	}
131
132	BReference& operator=(Type* other)
133	{
134		SetTo(other);
135		return *this;
136	}
137
138	template<typename OtherType>
139	BReference& operator=(const BReference<OtherType>& other)
140	{
141		SetTo(other.Get());
142		return *this;
143	}
144
145	bool operator==(const BReference<Type>& other) const
146	{
147		return fObject == other.fObject;
148	}
149
150	bool operator==(const Type* other) const
151	{
152		return fObject == other;
153	}
154
155	bool operator!=(const BReference<Type>& other) const
156	{
157		return fObject != other.fObject;
158	}
159
160	bool operator!=(const Type* other) const
161	{
162		return fObject != other;
163	}
164
165private:
166	Type*	fObject;
167};
168
169
170// #pragma mark - BReference<const>
171
172
173template<typename Type>
174class BReference<const Type> {
175public:
176	BReference(Type* object, bool alreadyHasReference = false)
177		:
178		fReference(object, alreadyHasReference)
179	{
180	}
181
182	BReference(const BReference<const Type>& other)
183		:
184		fReference(const_cast<Type*>(other.Get()))
185	{
186	}
187
188	template<typename OtherType>
189	BReference(const BReference<OtherType>& other)
190		:
191		fReference(other.Get())
192	{
193	}
194
195	void SetTo(Type* object, bool alreadyHasReference = false)
196	{
197		fReference.SetTo(object, alreadyHasReference);
198	}
199
200	void Unset()
201	{
202		fReference.Unset();
203	}
204
205	bool IsSet() const
206	{
207		return fReference.IsSet();
208	}
209
210	const Type* Get() const
211	{
212		return fReference.Get();
213	}
214
215	const Type* Detach()
216	{
217		return fReference.Detach();
218	}
219
220	const Type& operator*() const
221	{
222		return *fReference;
223	}
224
225	const Type* operator->() const
226	{
227		return fReference.Get();
228	}
229
230	operator const Type*() const
231	{
232		return fReference.Get();
233	}
234
235	BReference& operator=(const BReference<const Type>& other)
236	{
237		fReference = other.fReference;
238		return *this;
239	}
240
241	BReference& operator=(Type* other)
242	{
243		fReference = other;
244		return *this;
245	}
246
247	template<typename OtherType>
248	BReference& operator=(const BReference<OtherType>& other)
249	{
250		fReference = other.Get();
251		return *this;
252	}
253
254	bool operator==(const BReference<const Type>& other) const
255	{
256		return fReference == other.Get();
257	}
258
259	bool operator==(const Type* other) const
260	{
261		return fReference == other;
262	}
263
264	bool operator!=(const BReference<const Type>& other) const
265	{
266		return fReference != other.Get();
267	}
268
269	bool operator!=(const Type* other) const
270	{
271		return fReference != other;
272	}
273
274private:
275	BReference<Type> fReference;
276};
277
278
279#endif	// _REFERENCEABLE_H
280