1212525Simp/*
2212525Simp * Copyright 2009, Axel D��rfler, axeld@pinc-software.de.
3212525Simp * Distributed under the terms of the MIT License.
4212525Simp */
5212525Simp#ifndef _WEAK_REFERENCEABLE_H
6212525Simp#define _WEAK_REFERENCEABLE_H
7212525Simp
8212525Simp
9212525Simp#include <Referenceable.h>
10212525Simp
11212525Simp#include <new>
12212525Simp
13245652Sneel
14245652Sneelnamespace BPrivate {
15245652Sneel
16212525Simp
17212525Simpclass BWeakReferenceable;
18212525Simp
19212525Simp
20212525Simpclass WeakPointer : public BReferenceable {
21272322Sdelphijpublic:
22272322Sdelphij								WeakPointer(BWeakReferenceable* object);
23272322Sdelphij								~WeakPointer();
24212525Simp
25212525Simp			BWeakReferenceable*	Get();
26252356Sdavide			bool				Put();
27212525Simp
28212525Simp			int32				UseCount() const;
29212525Simp
30212525Simp			void				GetUnchecked();
31212525Simp
32212525Simpprivate:
33212525Simp			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