xref: /haiku/headers/private/shared/WeakReferenceable.h (revision 4466b89c65970de4c7236ac87faa2bee4589f413)
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 			vint32				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 	~BWeakReference()
91 	{
92 		Unset();
93 	}
94 
95 	void SetTo(Type* object)
96 	{
97 		Unset();
98 
99 		if (object != NULL)
100 			fPointer = object->GetWeakPointer();
101 	}
102 
103 	void SetTo(const BWeakReference<Type>& other)
104 	{
105 		Unset();
106 
107 		if (other.fPointer) {
108 			fPointer = other.fPointer;
109 			fPointer->AcquireReference();
110 		}
111 	}
112 
113 	void SetTo(const BReference<Type>& other)
114 	{
115 		SetTo(other.Get());
116 	}
117 
118 	void Unset()
119 	{
120 		if (fPointer != NULL) {
121 			fPointer->ReleaseReference();
122 			fPointer = NULL;
123 		}
124 	}
125 
126 	bool IsAlive()
127 	{
128 		if (fPointer == NULL)
129 			return false;
130 		Type* object = static_cast<Type*>(fPointer->Get());
131 		if (object == NULL)
132 			return false;
133 		fPointer->Put();
134 		return true;
135 	}
136 
137 	BReference<Type> GetReference()
138 	{
139 		Type* object = static_cast<Type*>(fPointer->Get());
140 		return BReference<Type>(object, true);
141 	}
142 
143 	BWeakReference& operator=(const BWeakReference<Type>& other)
144 	{
145 		if (this == &other)
146 			return *this;
147 
148 		SetTo(other.fPointer);
149 		return *this;
150 	}
151 
152 	BWeakReference& operator=(const Type& other)
153 	{
154 		SetTo(&other);
155 		return *this;
156 	}
157 
158 	BWeakReference& operator=(Type* other)
159 	{
160 		SetTo(other);
161 		return *this;
162 	}
163 
164 	BWeakReference& operator=(const BReference<Type>& other)
165 	{
166 		SetTo(other.Get());
167 		return *this;
168 	}
169 
170 	bool operator==(const BWeakReference<Type>& other) const
171 	{
172 		return fPointer == other.fPointer;
173 	}
174 
175 	bool operator!=(const BWeakReference<Type>& other) const
176 	{
177 		return fPointer != other.fPointer;
178 	}
179 
180 private:
181 	WeakPointer*	fPointer;
182 };
183 
184 
185 //	#pragma mark -
186 
187 
188 inline
189 WeakPointer::WeakPointer(BWeakReferenceable* object)
190 	:
191 	fUseCount(1),
192 	fObject(object)
193 {
194 }
195 
196 
197 inline
198 WeakPointer::~WeakPointer()
199 {
200 }
201 
202 
203 inline BWeakReferenceable*
204 WeakPointer::Get()
205 {
206 	int32 count = -11;
207 
208 	do {
209 		count = atomic_get(&fUseCount);
210 		if (count == 0)
211 			return NULL;
212 	} while (atomic_test_and_set(&fUseCount, count + 1, count) != count);
213 
214 	return fObject;
215 }
216 
217 
218 inline bool
219 WeakPointer::Put()
220 {
221 	if (atomic_add(&fUseCount, -1) == 1) {
222 		delete fObject;
223 		return true;
224 	}
225 
226 	return false;
227 }
228 
229 
230 inline int32
231 WeakPointer::UseCount() const
232 {
233 	return fUseCount;
234 }
235 
236 
237 inline void
238 WeakPointer::GetUnchecked()
239 {
240 	atomic_add(&fUseCount, 1);
241 }
242 
243 
244 //	#pragma -
245 
246 
247 inline
248 BWeakReferenceable::BWeakReferenceable()
249 	:
250 	fPointer(new(std::nothrow) WeakPointer(this))
251 {
252 }
253 
254 
255 inline
256 BWeakReferenceable::~BWeakReferenceable()
257 {
258 	fPointer->ReleaseReference();
259 }
260 
261 
262 inline status_t
263 BWeakReferenceable::InitCheck()
264 {
265 	if (fPointer == NULL)
266 		return B_NO_MEMORY;
267 	return B_OK;
268 }
269 
270 
271 inline WeakPointer*
272 BWeakReferenceable::GetWeakPointer()
273 {
274 	fPointer->AcquireReference();
275 	return fPointer;
276 }
277 
278 }	// namespace BPrivate
279 
280 using BPrivate::BWeakReferenceable;
281 using BPrivate::BWeakReference;
282 
283 #endif	// _WEAK_REFERENCEABLE_H
284