xref: /haiku/headers/private/shared/WeakReferenceable.h (revision 1a76488fc88584bf66b9751d7fb9b6527ac20d87)
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 		Type* object = static_cast<Type*>(fPointer->Get());
174 		return BReference<Type>(object, true);
175 	}
176 
177 	BWeakReference& operator=(const BWeakReference<Type>& other)
178 	{
179 		if (this == &other)
180 			return *this;
181 
182 		SetTo(other);
183 		return *this;
184 	}
185 
186 	BWeakReference& operator=(Type* other)
187 	{
188 		SetTo(other);
189 		return *this;
190 	}
191 
192 	BWeakReference& operator=(const BReference<Type>& other)
193 	{
194 		SetTo(other.Get());
195 		return *this;
196 	}
197 
198 	template<typename OtherType>
199 	BWeakReference& operator=(const BReference<OtherType>& other)
200 	{
201 		SetTo(other.Get());
202 		return *this;
203 	}
204 
205 	template<typename OtherType>
206 	BWeakReference& operator=(const BWeakReference<OtherType>& other)
207 	{
208 		SetTo(other);
209 		return *this;
210 	}
211 
212 	bool operator==(const BWeakReference<Type>& other) const
213 	{
214 		return fPointer == other.fPointer;
215 	}
216 
217 	bool operator!=(const BWeakReference<Type>& other) const
218 	{
219 		return fPointer != other.fPointer;
220 	}
221 
222 	/*!	Do not use this if you do not know what you are doing. The WeakPointer
223 		is for internal use only.
224 	*/
225 	const WeakPointer* PrivatePointer() const
226 	{
227 		return fPointer;
228 	}
229 
230 private:
231 	WeakPointer*	fPointer;
232 };
233 
234 
235 }	// namespace BPrivate
236 
237 using BPrivate::BWeakReferenceable;
238 using BPrivate::BWeakReference;
239 
240 #endif	// _WEAK_REFERENCEABLE_H
241