xref: /haiku/headers/private/shared/WeakReferenceable.h (revision dd2a1e350b303b855a50fd64e6cb55618be1ae6a)
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 			friend class BWeakReferenceable;
34 
35 			int32				fUseCount;
36 			BWeakReferenceable*	fObject;
37 };
38 
39 
40 class BWeakReferenceable {
41 public:
42 								BWeakReferenceable();
43 	virtual						~BWeakReferenceable();
44 
45 			status_t			InitCheck();
46 
47 			void				AcquireReference()
48 									{ fPointer->GetUnchecked(); }
49 
50 			bool				ReleaseReference()
51 									{ return fPointer->Put(); }
52 
53 			int32				CountReferences() const
54 									{ return fPointer->UseCount(); }
55 
56 			WeakPointer*		GetWeakPointer();
57 private:
58 			WeakPointer*		fPointer;
59 };
60 
61 
62 template<typename Type>
63 class BWeakReference {
64 public:
65 	BWeakReference()
66 		:
67 		fPointer(NULL)
68 	{
69 	}
70 
71 	BWeakReference(Type* object)
72 		:
73 		fPointer(NULL)
74 	{
75 		SetTo(object);
76 	}
77 
78 	BWeakReference(const BWeakReference<Type>& other)
79 		:
80 		fPointer(NULL)
81 	{
82 		SetTo(other);
83 	}
84 
85 	BWeakReference(const BReference<Type>& other)
86 		:
87 		fPointer(NULL)
88 	{
89 		SetTo(other);
90 	}
91 
92 	template<typename OtherType>
93 	BWeakReference(const BReference<OtherType>& other)
94 		:
95 		fPointer(NULL)
96 	{
97 		SetTo(other.Get());
98 	}
99 
100 	template<typename OtherType>
101 	BWeakReference(const BWeakReference<OtherType>& other)
102 		:
103 		fPointer(NULL)
104 	{
105 		SetTo(other);
106 	}
107 
108 	~BWeakReference()
109 	{
110 		Unset();
111 	}
112 
113 	void SetTo(Type* object)
114 	{
115 		Unset();
116 
117 		if (object != NULL)
118 			fPointer = object->GetWeakPointer();
119 	}
120 
121 	void SetTo(const BWeakReference<Type>& other)
122 	{
123 		Unset();
124 
125 		if (other.fPointer) {
126 			fPointer = other.fPointer;
127 			fPointer->AcquireReference();
128 		}
129 	}
130 
131 	template<typename OtherType>
132 	void SetTo(const BWeakReference<OtherType>& other)
133 	{
134 		// Just a compiler check if the types are compatible.
135 		OtherType* otherDummy = NULL;
136 		Type* dummy = otherDummy;
137 		dummy = NULL;
138 
139 		Unset();
140 
141 		if (other.PrivatePointer()) {
142 			fPointer = const_cast<WeakPointer*>(other.PrivatePointer());
143 			fPointer->AcquireReference();
144 		}
145 	}
146 
147 	void SetTo(const BReference<Type>& other)
148 	{
149 		SetTo(other.Get());
150 	}
151 
152 	void Unset()
153 	{
154 		if (fPointer != NULL) {
155 			fPointer->ReleaseReference();
156 			fPointer = NULL;
157 		}
158 	}
159 
160 	bool IsAlive()
161 	{
162 		if (fPointer == NULL)
163 			return false;
164 		Type* object = static_cast<Type*>(fPointer->Get());
165 		if (object == NULL)
166 			return false;
167 		fPointer->Put();
168 		return true;
169 	}
170 
171 	BReference<Type> GetReference()
172 	{
173 		if (fPointer == NULL)
174 			return BReference<Type>();
175 
176 		Type* object = static_cast<Type*>(fPointer->Get());
177 		return BReference<Type>(object, true);
178 	}
179 
180 	BWeakReference& operator=(const BWeakReference<Type>& other)
181 	{
182 		if (this == &other)
183 			return *this;
184 
185 		SetTo(other);
186 		return *this;
187 	}
188 
189 	BWeakReference& operator=(Type* other)
190 	{
191 		SetTo(other);
192 		return *this;
193 	}
194 
195 	BWeakReference& operator=(const BReference<Type>& other)
196 	{
197 		SetTo(other.Get());
198 		return *this;
199 	}
200 
201 	template<typename OtherType>
202 	BWeakReference& operator=(const BReference<OtherType>& other)
203 	{
204 		SetTo(other.Get());
205 		return *this;
206 	}
207 
208 	template<typename OtherType>
209 	BWeakReference& operator=(const BWeakReference<OtherType>& other)
210 	{
211 		SetTo(other);
212 		return *this;
213 	}
214 
215 	bool operator==(const BWeakReference<Type>& other) const
216 	{
217 		return fPointer == other.fPointer;
218 	}
219 
220 	bool operator!=(const BWeakReference<Type>& other) const
221 	{
222 		return fPointer != other.fPointer;
223 	}
224 
225 	/*!	Do not use this if you do not know what you are doing. The WeakPointer
226 		is for internal use only.
227 	*/
228 	const WeakPointer* PrivatePointer() const
229 	{
230 		return fPointer;
231 	}
232 
233 private:
234 	WeakPointer*	fPointer;
235 };
236 
237 
238 }	// namespace BPrivate
239 
240 using BPrivate::BWeakReferenceable;
241 using BPrivate::BWeakReference;
242 
243 #endif	// _WEAK_REFERENCEABLE_H
244