xref: /haiku/headers/private/shared/WeakReferenceable.h (revision 3b07762c548ec4016dea480d1061577cd15ec614)
1 /*
2  * Copyright 2009, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef _WEAK_REFERENCEABLE_H
6 #define _WEAK_REFERENCEABLE_H
7 
8 
9 #include <Referenceable.h>
10 
11 #include <new>
12 
13 
14 namespace BPrivate {
15 
16 
17 class BWeakReferenceable;
18 
19 
20 class WeakPointer : public BReferenceable {
21 public:
22 								WeakPointer(BWeakReferenceable* object);
23 								~WeakPointer();
24 
25 			BWeakReferenceable*	Get();
26 			bool				Put();
27 
28 			int32				UseCount() const;
29 
30 			void				GetUnchecked();
31 
32 private:
33 			int32				fUseCount;
34 			BWeakReferenceable*	fObject;
35 };
36 
37 
38 class BWeakReferenceable {
39 public:
40 								BWeakReferenceable();
41 	virtual						~BWeakReferenceable();
42 
43 			status_t			InitCheck();
44 
45 			void				AcquireReference()
46 									{ fPointer->GetUnchecked(); }
47 
48 			bool				ReleaseReference()
49 									{ return fPointer->Put(); }
50 
51 			int32				CountReferences() const
52 									{ return fPointer->UseCount(); }
53 
54 			WeakPointer*		GetWeakPointer();
55 private:
56 			WeakPointer*		fPointer;
57 };
58 
59 
60 template<typename Type>
61 class BWeakReference {
62 public:
63 	BWeakReference()
64 		:
65 		fPointer(NULL)
66 	{
67 	}
68 
69 	BWeakReference(Type* object)
70 		:
71 		fPointer(NULL)
72 	{
73 		SetTo(object);
74 	}
75 
76 	BWeakReference(const BWeakReference<Type>& other)
77 		:
78 		fPointer(NULL)
79 	{
80 		SetTo(other);
81 	}
82 
83 	BWeakReference(const BReference<Type>& other)
84 		:
85 		fPointer(NULL)
86 	{
87 		SetTo(other);
88 	}
89 
90 	template<typename OtherType>
91 	BWeakReference(const BReference<OtherType>& other)
92 		:
93 		fPointer(NULL)
94 	{
95 		SetTo(other.Get());
96 	}
97 
98 	template<typename OtherType>
99 	BWeakReference(const BWeakReference<OtherType>& other)
100 		:
101 		fPointer(NULL)
102 	{
103 		SetTo(other);
104 	}
105 
106 	~BWeakReference()
107 	{
108 		Unset();
109 	}
110 
111 	void SetTo(Type* object)
112 	{
113 		Unset();
114 
115 		if (object != NULL)
116 			fPointer = object->GetWeakPointer();
117 	}
118 
119 	void SetTo(const BWeakReference<Type>& other)
120 	{
121 		Unset();
122 
123 		if (other.fPointer) {
124 			fPointer = other.fPointer;
125 			fPointer->AcquireReference();
126 		}
127 	}
128 
129 	template<typename OtherType>
130 	void SetTo(const BWeakReference<OtherType>& other)
131 	{
132 		// Just a compiler check if the types are compatible.
133 		OtherType* otherDummy = NULL;
134 		Type* dummy = otherDummy;
135 		dummy = NULL;
136 
137 		Unset();
138 
139 		if (other.PrivatePointer()) {
140 			fPointer = const_cast<WeakPointer*>(other.PrivatePointer());
141 			fPointer->AcquireReference();
142 		}
143 	}
144 
145 	void SetTo(const BReference<Type>& other)
146 	{
147 		SetTo(other.Get());
148 	}
149 
150 	void Unset()
151 	{
152 		if (fPointer != NULL) {
153 			fPointer->ReleaseReference();
154 			fPointer = NULL;
155 		}
156 	}
157 
158 	bool IsAlive()
159 	{
160 		if (fPointer == NULL)
161 			return false;
162 		Type* object = static_cast<Type*>(fPointer->Get());
163 		if (object == NULL)
164 			return false;
165 		fPointer->Put();
166 		return true;
167 	}
168 
169 	BReference<Type> GetReference()
170 	{
171 		Type* object = static_cast<Type*>(fPointer->Get());
172 		return BReference<Type>(object, true);
173 	}
174 
175 	BWeakReference& operator=(const BWeakReference<Type>& other)
176 	{
177 		if (this == &other)
178 			return *this;
179 
180 		SetTo(other);
181 		return *this;
182 	}
183 
184 	BWeakReference& operator=(Type* other)
185 	{
186 		SetTo(other);
187 		return *this;
188 	}
189 
190 	BWeakReference& operator=(const BReference<Type>& other)
191 	{
192 		SetTo(other.Get());
193 		return *this;
194 	}
195 
196 	template<typename OtherType>
197 	BWeakReference& operator=(const BReference<OtherType>& other)
198 	{
199 		SetTo(other.Get());
200 		return *this;
201 	}
202 
203 	template<typename OtherType>
204 	BWeakReference& operator=(const BWeakReference<OtherType>& other)
205 	{
206 		SetTo(other);
207 		return *this;
208 	}
209 
210 	bool operator==(const BWeakReference<Type>& other) const
211 	{
212 		return fPointer == other.fPointer;
213 	}
214 
215 	bool operator!=(const BWeakReference<Type>& other) const
216 	{
217 		return fPointer != other.fPointer;
218 	}
219 
220 	/*!	Do not use this if you do not know what you are doing. The WeakPointer
221 		is for internal use only.
222 	*/
223 	const WeakPointer* PrivatePointer() const
224 	{
225 		return fPointer;
226 	}
227 
228 private:
229 	WeakPointer*	fPointer;
230 };
231 
232 
233 //	#pragma mark -
234 
235 
236 inline
237 WeakPointer::WeakPointer(BWeakReferenceable* object)
238 	:
239 	fUseCount(1),
240 	fObject(object)
241 {
242 }
243 
244 
245 inline
246 WeakPointer::~WeakPointer()
247 {
248 }
249 
250 
251 inline BWeakReferenceable*
252 WeakPointer::Get()
253 {
254 	int32 count = -11;
255 
256 	do {
257 		count = atomic_get(&fUseCount);
258 		if (count == 0)
259 			return NULL;
260 	} while (atomic_test_and_set(&fUseCount, count + 1, count) != count);
261 
262 	return fObject;
263 }
264 
265 
266 inline bool
267 WeakPointer::Put()
268 {
269 	if (atomic_add(&fUseCount, -1) == 1) {
270 		delete fObject;
271 		return true;
272 	}
273 
274 	return false;
275 }
276 
277 
278 inline int32
279 WeakPointer::UseCount() const
280 {
281 	return fUseCount;
282 }
283 
284 
285 inline void
286 WeakPointer::GetUnchecked()
287 {
288 	atomic_add(&fUseCount, 1);
289 }
290 
291 
292 //	#pragma -
293 
294 
295 inline
296 BWeakReferenceable::BWeakReferenceable()
297 	:
298 	fPointer(new(std::nothrow) WeakPointer(this))
299 {
300 }
301 
302 
303 inline
304 BWeakReferenceable::~BWeakReferenceable()
305 {
306 	fPointer->ReleaseReference();
307 }
308 
309 
310 inline status_t
311 BWeakReferenceable::InitCheck()
312 {
313 	if (fPointer == NULL)
314 		return B_NO_MEMORY;
315 	return B_OK;
316 }
317 
318 
319 inline WeakPointer*
320 BWeakReferenceable::GetWeakPointer()
321 {
322 	fPointer->AcquireReference();
323 	return fPointer;
324 }
325 
326 }	// namespace BPrivate
327 
328 using BPrivate::BWeakReferenceable;
329 using BPrivate::BWeakReference;
330 
331 #endif	// _WEAK_REFERENCEABLE_H
332