Referenceable.h revision e9b82428
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, typename ConstType = Type>
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
64	template<typename OtherType>
65	BReference(const BReference<OtherType>& other)
66		:
67		fObject(NULL)
68	{
69		SetTo(other.Get());
70	}
71
72	~BReference()
73	{
74		Unset();
75	}
76
77	void SetTo(Type* object, bool alreadyHasReference = false)
78	{
79		if (object != NULL && !alreadyHasReference)
80			object->AcquireReference();
81
82		Unset();
83
84		fObject = object;
85	}
86
87	void Unset()
88	{
89		if (fObject) {
90			fObject->ReleaseReference();
91			fObject = NULL;
92		}
93	}
94
95	ConstType* Get() const
96	{
97		return fObject;
98	}
99
100	ConstType* Detach()
101	{
102		Type* object = fObject;
103		fObject = NULL;
104		return object;
105	}
106
107	ConstType& operator*() const
108	{
109		return *fObject;
110	}
111
112	ConstType* operator->() const
113	{
114		return fObject;
115	}
116
117	operator ConstType*() const
118	{
119		return fObject;
120	}
121
122	BReference& operator=(const BReference<Type, ConstType>& other)
123	{
124		SetTo(other.fObject);
125		return *this;
126	}
127
128	BReference& operator=(Type* other)
129	{
130		SetTo(other);
131		return *this;
132	}
133
134	template<typename OtherType, typename OtherConstType>
135	BReference& operator=(const BReference<OtherType, OtherConstType>& other)
136	{
137		SetTo(other.Get());
138		return *this;
139	}
140
141	bool operator==(const BReference<Type, ConstType>& other) const
142	{
143		return fObject == other.fObject;
144	}
145
146	bool operator==(const Type* other) const
147	{
148		return fObject == other;
149	}
150
151	bool operator!=(const BReference<Type, ConstType>& other) const
152	{
153		return fObject != other.fObject;
154	}
155
156	bool operator!=(const Type* other) const
157	{
158		return fObject != other;
159	}
160
161private:
162	Type*	fObject;
163};
164
165
166// #pragma mark - BReference
167
168
169template<typename Type = BReferenceable>
170class BConstReference: public BReference<Type, const Type> {
171public:
172	BConstReference()
173		:
174		BReference<Type, const Type>()
175	{
176	}
177
178	BConstReference(Type* object, bool alreadyHasReference = false)
179		:
180		BReference<Type, const Type>(object, alreadyHasReference)
181	{
182	}
183
184	BConstReference(const BReference<Type>& other)
185		:
186		BReference<Type, const Type>(other)
187	{
188	}
189
190	// Allow assignment of a const reference from a mutable one (but not the
191	// reverse).
192	BConstReference& operator=(const BReference<Type, Type>& other)
193	{
194		SetTo(other.Get());
195		return *this;
196	}
197
198};
199
200
201#endif	// _REFERENCEABLE_H
202