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
14namespace BPrivate {
15
16
17class BWeakReferenceable;
18
19
20class WeakPointer : public BReferenceable {
21public:
22								WeakPointer(BWeakReferenceable* object);
23								~WeakPointer();
24
25			BWeakReferenceable*	Get();
26			bool				Put();
27
28			int32				UseCount() const;
29
30			void				GetUnchecked();
31
32private:
33			friend class BWeakReferenceable;
34
35			int32				fUseCount;
36			BWeakReferenceable*	fObject;
37};
38
39
40class BWeakReferenceable {
41public:
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();
57private:
58			WeakPointer*		fPointer;
59};
60
61
62template<typename Type>
63class BWeakReference {
64public:
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
233private:
234	WeakPointer*	fPointer;
235};
236
237
238}	// namespace BPrivate
239
240using BPrivate::BWeakReferenceable;
241using BPrivate::BWeakReference;
242
243#endif	// _WEAK_REFERENCEABLE_H
244