xref: /haiku/headers/os/support/Referenceable.h (revision 4bd0c1066b227cec4b79883bdef697c7a27f2e90)
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 
15 class BReferenceable {
16 public:
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 
28 protected:
29 	virtual	void				FirstReferenceAcquired();
30 	virtual	void				LastReferenceReleased();
31 
32 protected:
33 			int32				fReferenceCount;
34 };
35 
36 
37 // #pragma mark - BReference
38 
39 
40 template<typename Type = BReferenceable>
41 class BReference {
42 public:
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 
160 private:
161 	Type*	fObject;
162 };
163 
164 
165 // #pragma mark - BReference<const>
166 
167 
168 template<typename Type>
169 class BReference<const Type> {
170 public:
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 
261 private:
262 	BReference<Type> fReference;
263 };
264 
265 
266 #endif	// _REFERENCEABLE_H
267