xref: /haiku/headers/private/shared/WeakReferenceable.h (revision 16d5c24e533eb14b7b8a99ee9f3ec9ba66335b1e)
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 
12 namespace BPrivate {
13 
14 template<typename Type> class WeakReferenceable;
15 
16 template<typename Type>
17 class WeakPointer : public Referenceable {
18 public:
19 			Type*				Get();
20 			bool				Put();
21 
22 			int32				UseCount() const;
23 
24 private:
25 	friend class WeakReferenceable<Type>;
26 
27 								WeakPointer(Type* object);
28 								~WeakPointer();
29 
30 private:
31 			void				_GetUnchecked();
32 
33 private:
34 			vint32				fUseCount;
35 			Type*				fObject;
36 };
37 
38 template<typename Type>
39 class WeakReferenceable {
40 public:
41 								WeakReferenceable(Type* object);
42 								~WeakReferenceable();
43 
44 			void				AddReference()
45 									{ fPointer->_GetUnchecked(); }
46 
47 			bool				RemoveReference()
48 									{ return fPointer->Put(); }
49 
50 			int32				CountReferences() const
51 									{ return fPointer->UseCount(); }
52 
53 			WeakPointer<Type>*	GetWeakPointer();
54 
55 protected:
56 			WeakPointer<Type>*	fPointer;
57 };
58 
59 template<typename Type>
60 class WeakReference {
61 public:
62 	WeakReference()
63 		:
64 		fPointer(NULL),
65 		fObject(NULL)
66 	{
67 	}
68 
69 	WeakReference(Type* object)
70 		:
71 		fPointer(NULL),
72 		fObject(NULL)
73 	{
74 		SetTo(object);
75 	}
76 
77 	WeakReference(WeakPointer<Type>& other)
78 		:
79 		fPointer(NULL),
80 		fObject(NULL)
81 	{
82 		SetTo(&other);
83 	}
84 
85 	WeakReference(WeakPointer<Type>* other)
86 		:
87 		fPointer(NULL),
88 		fObject(NULL)
89 	{
90 		SetTo(other);
91 	}
92 
93 	WeakReference(const WeakReference<Type>& other)
94 		:
95 		fPointer(NULL),
96 		fObject(NULL)
97 	{
98 		SetTo(other.fPointer);
99 	}
100 
101 	~WeakReference()
102 	{
103 		Unset();
104 	}
105 
106 	void SetTo(Type* object)
107 	{
108 		Unset();
109 
110 		if (object != NULL) {
111 			fPointer = object->GetWeakPointer();
112 			fObject = fPointer->Get();
113 		}
114 	}
115 
116 	void SetTo(WeakPointer<Type>* pointer)
117 	{
118 		Unset();
119 
120 		if (pointer != NULL) {
121 			fPointer = pointer;
122 			fPointer->AddReference();
123 			fObject = pointer->Get();
124 		}
125 	}
126 
127 	void Unset()
128 	{
129 		if (fPointer != NULL) {
130 			if (fObject != NULL) {
131 				fPointer->Put();
132 				fObject = NULL;
133 			}
134 			fPointer->RemoveReference();
135 			fPointer = NULL;
136 		}
137 	}
138 
139 	Type* Get() const
140 	{
141 		return fObject;
142 	}
143 
144 	Type* Detach()
145 	{
146 		Type* object = fObject;
147 		Unset();
148 		return object;
149 	}
150 
151 	Type& operator*() const
152 	{
153 		return *fObject;
154 	}
155 
156 	operator Type*() const
157 	{
158 		return fObject;
159 	}
160 
161 	Type* operator->() const
162 	{
163 		return fObject;
164 	}
165 
166 	WeakReference& operator=(const WeakReference<Type>& other)
167 	{
168 		if (this == &other)
169 			return *this;
170 
171 		SetTo(other.fPointer);
172 		return *this;
173 	}
174 
175 	WeakReference& operator=(const Type& other)
176 	{
177 		SetTo(&other);
178 		return *this;
179 	}
180 
181 	WeakReference& operator=(WeakPointer<Type>& other)
182 	{
183 		SetTo(&other);
184 		return *this;
185 	}
186 
187 	WeakReference& operator=(WeakPointer<Type>* other)
188 	{
189 		SetTo(other);
190 		return *this;
191 	}
192 
193 	bool operator==(const WeakReference<Type>& other) const
194 	{
195 		return fPointer == other.fPointer;
196 	}
197 
198 	bool operator!=(const WeakReference<Type>& other) const
199 	{
200 		return fPointer != other.fPointer;
201 	}
202 
203 private:
204 	WeakPointer<Type>*	fPointer;
205 	Type*			fObject;
206 };
207 
208 
209 //	#pragma mark -
210 
211 
212 template<typename Type>
213 inline Type*
214 WeakPointer<Type>::Get()
215 {
216 	int32 count = -11;
217 
218 	do {
219 		count = atomic_get(&fUseCount);
220 		if (count == 0)
221 			return NULL;
222 	} while (atomic_test_and_set(&fUseCount, count + 1, count) != count);
223 
224 	return fObject;
225 }
226 
227 
228 template<typename Type>
229 inline bool
230 WeakPointer<Type>::Put()
231 {
232 	if (atomic_add(&fUseCount, -1) == 1) {
233 		delete fObject;
234 		return true;
235 	}
236 
237 	return false;
238 }
239 
240 
241 template<typename Type>
242 inline int32
243 WeakPointer<Type>::UseCount() const
244 {
245 	return fUseCount;
246 }
247 
248 
249 template<typename Type>
250 inline
251 WeakPointer<Type>::WeakPointer(Type* object)
252 	:
253 	fUseCount(1),
254 	fObject(object)
255 {
256 }
257 
258 
259 template<typename Type>
260 inline
261 WeakPointer<Type>::~WeakPointer()
262 {
263 }
264 
265 
266 template<typename Type>
267 inline void
268 WeakPointer<Type>::_GetUnchecked()
269 {
270 	atomic_add(&fUseCount, 1);
271 }
272 
273 
274 //	#pragma -
275 
276 
277 template<typename Type>
278 inline
279 WeakReferenceable<Type>::WeakReferenceable(Type* object)
280 	:
281 	fPointer(new WeakPointer<Type>(object))
282 {
283 }
284 
285 
286 template<typename Type>
287 inline
288 WeakReferenceable<Type>::~WeakReferenceable()
289 {
290 	fPointer->RemoveReference();
291 }
292 
293 
294 template<typename Type>
295 inline WeakPointer<Type>*
296 WeakReferenceable<Type>::GetWeakPointer()
297 {
298 	fPointer->AddReference();
299 	return fPointer;
300 }
301 
302 }	// namespace BPrivate
303 
304 using BPrivate::WeakReferenceable;
305 using BPrivate::WeakPointer;
306 using BPrivate::WeakReference;
307 
308 #endif	// _WEAK_REFERENCEABLE_H
309