xref: /haiku/headers/os/support/Referenceable.h (revision fc7456e9b1ec38c941134ed6d01c438cf289381e)
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 atomic_get((int32*)&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 	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 
165 private:
166 	Type*	fObject;
167 };
168 
169 
170 // #pragma mark - BReference<const>
171 
172 
173 template<typename Type>
174 class BReference<const Type> {
175 public:
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 
274 private:
275 	BReference<Type> fReference;
276 };
277 
278 
279 #endif	// _REFERENCEABLE_H
280