1e5c31af7Sopenharmony_ci#ifndef _DESHAREDPTR_HPP
2e5c31af7Sopenharmony_ci#define _DESHAREDPTR_HPP
3e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
4e5c31af7Sopenharmony_ci * drawElements C++ Base Library
5e5c31af7Sopenharmony_ci * -----------------------------
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
8e5c31af7Sopenharmony_ci *
9e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
10e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
11e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
14e5c31af7Sopenharmony_ci *
15e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
16e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
17e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
19e5c31af7Sopenharmony_ci * limitations under the License.
20e5c31af7Sopenharmony_ci *
21e5c31af7Sopenharmony_ci *//*!
22e5c31af7Sopenharmony_ci * \file
23e5c31af7Sopenharmony_ci * \brief Shared pointer.
24e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#include "deDefs.hpp"
27e5c31af7Sopenharmony_ci#include "deAtomic.h"
28e5c31af7Sopenharmony_ci
29e5c31af7Sopenharmony_ci#include <exception>
30e5c31af7Sopenharmony_ci#include <algorithm>
31e5c31af7Sopenharmony_ci
32e5c31af7Sopenharmony_cinamespace de
33e5c31af7Sopenharmony_ci{
34e5c31af7Sopenharmony_ci
35e5c31af7Sopenharmony_ci//! Shared pointer self-test.
36e5c31af7Sopenharmony_civoid SharedPtr_selfTest (void);
37e5c31af7Sopenharmony_ci
38e5c31af7Sopenharmony_ciclass DeadReferenceException : public std::exception
39e5c31af7Sopenharmony_ci{
40e5c31af7Sopenharmony_cipublic:
41e5c31af7Sopenharmony_ci				DeadReferenceException	(void) throw()
42e5c31af7Sopenharmony_ci		: std::exception()
43e5c31af7Sopenharmony_ci	{
44e5c31af7Sopenharmony_ci	}
45e5c31af7Sopenharmony_ci
46e5c31af7Sopenharmony_ci	const char*	what					(void) const throw()
47e5c31af7Sopenharmony_ci	{
48e5c31af7Sopenharmony_ci		return "DeadReferenceException";
49e5c31af7Sopenharmony_ci	}
50e5c31af7Sopenharmony_ci};
51e5c31af7Sopenharmony_ci
52e5c31af7Sopenharmony_cistruct SharedPtrStateBase
53e5c31af7Sopenharmony_ci{
54e5c31af7Sopenharmony_ci	SharedPtrStateBase (void)
55e5c31af7Sopenharmony_ci		: strongRefCount	(0)
56e5c31af7Sopenharmony_ci		, weakRefCount		(0)
57e5c31af7Sopenharmony_ci	{
58e5c31af7Sopenharmony_ci	}
59e5c31af7Sopenharmony_ci
60e5c31af7Sopenharmony_ci	virtual				~SharedPtrStateBase	(void) throw() {}
61e5c31af7Sopenharmony_ci	virtual void		deletePtr			(void) throw() = 0;
62e5c31af7Sopenharmony_ci
63e5c31af7Sopenharmony_ci	volatile deInt32	strongRefCount;
64e5c31af7Sopenharmony_ci	volatile deInt32	weakRefCount;		//!< WeakPtr references + StrongPtr references.
65e5c31af7Sopenharmony_ci};
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_citemplate<typename Type, typename Deleter>
68e5c31af7Sopenharmony_cistruct SharedPtrState : public SharedPtrStateBase
69e5c31af7Sopenharmony_ci{
70e5c31af7Sopenharmony_ci	SharedPtrState (Type* ptr, Deleter deleter)
71e5c31af7Sopenharmony_ci		: m_ptr		(ptr)
72e5c31af7Sopenharmony_ci		, m_deleter	(deleter)
73e5c31af7Sopenharmony_ci	{
74e5c31af7Sopenharmony_ci	}
75e5c31af7Sopenharmony_ci
76e5c31af7Sopenharmony_ci	virtual ~SharedPtrState (void) throw()
77e5c31af7Sopenharmony_ci	{
78e5c31af7Sopenharmony_ci		DE_ASSERT(!m_ptr);
79e5c31af7Sopenharmony_ci	}
80e5c31af7Sopenharmony_ci
81e5c31af7Sopenharmony_ci	virtual void deletePtr (void) throw()
82e5c31af7Sopenharmony_ci	{
83e5c31af7Sopenharmony_ci		m_deleter(m_ptr);
84e5c31af7Sopenharmony_ci		m_ptr = DE_NULL;
85e5c31af7Sopenharmony_ci	}
86e5c31af7Sopenharmony_ci
87e5c31af7Sopenharmony_ciprivate:
88e5c31af7Sopenharmony_ci	Type*		m_ptr;
89e5c31af7Sopenharmony_ci	Deleter		m_deleter;
90e5c31af7Sopenharmony_ci};
91e5c31af7Sopenharmony_ci
92e5c31af7Sopenharmony_citemplate<typename T>
93e5c31af7Sopenharmony_ciclass SharedPtr;
94e5c31af7Sopenharmony_ci
95e5c31af7Sopenharmony_citemplate<typename T>
96e5c31af7Sopenharmony_ciclass WeakPtr;
97e5c31af7Sopenharmony_ci
98e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
99e5c31af7Sopenharmony_ci * \brief Shared pointer
100e5c31af7Sopenharmony_ci *
101e5c31af7Sopenharmony_ci * SharedPtr is smart pointer for managing shared ownership to a pointer.
102e5c31af7Sopenharmony_ci * Multiple SharedPtrs can maintain ownership to the pointer and it is
103e5c31af7Sopenharmony_ci * destructed when last SharedPtr is destroyed.
104e5c31af7Sopenharmony_ci *
105e5c31af7Sopenharmony_ci * SharedPtr can also be NULL.
106e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
107e5c31af7Sopenharmony_citemplate<typename T>
108e5c31af7Sopenharmony_ciclass SharedPtr
109e5c31af7Sopenharmony_ci{
110e5c31af7Sopenharmony_cipublic:
111e5c31af7Sopenharmony_ci								SharedPtr			(void);
112e5c31af7Sopenharmony_ci								SharedPtr			(const SharedPtr<T>& other);
113e5c31af7Sopenharmony_ci	explicit					SharedPtr			(T* ptr);
114e5c31af7Sopenharmony_ci
115e5c31af7Sopenharmony_ci	template<typename Deleter>
116e5c31af7Sopenharmony_ci								SharedPtr			(T* ptr, Deleter deleter);
117e5c31af7Sopenharmony_ci
118e5c31af7Sopenharmony_ci	template<typename Y>
119e5c31af7Sopenharmony_ci	explicit					SharedPtr			(const SharedPtr<Y>& other);
120e5c31af7Sopenharmony_ci
121e5c31af7Sopenharmony_ci	template<typename Y>
122e5c31af7Sopenharmony_ci	explicit					SharedPtr			(const WeakPtr<Y>& other);
123e5c31af7Sopenharmony_ci
124e5c31af7Sopenharmony_ci								~SharedPtr			(void);
125e5c31af7Sopenharmony_ci
126e5c31af7Sopenharmony_ci	template<typename Y>
127e5c31af7Sopenharmony_ci	SharedPtr&					operator=			(const SharedPtr<Y>& other);
128e5c31af7Sopenharmony_ci	SharedPtr&					operator=			(const SharedPtr<T>& other);
129e5c31af7Sopenharmony_ci
130e5c31af7Sopenharmony_ci	template<typename Y>
131e5c31af7Sopenharmony_ci	SharedPtr&					operator=			(const WeakPtr<Y>& other);
132e5c31af7Sopenharmony_ci
133e5c31af7Sopenharmony_ci	T*							get					(void) const throw() { return m_ptr;	}	//!< Get stored pointer.
134e5c31af7Sopenharmony_ci	T*							operator->			(void) const throw() { return m_ptr;	}	//!< Get stored pointer.
135e5c31af7Sopenharmony_ci	T&							operator*			(void) const throw() { return *m_ptr;	}	//!< De-reference pointer.
136e5c31af7Sopenharmony_ci
137e5c31af7Sopenharmony_ci	operator					bool				(void) const throw() { return !!m_ptr;	}
138e5c31af7Sopenharmony_ci
139e5c31af7Sopenharmony_ci	void						swap				(SharedPtr<T>& other);
140e5c31af7Sopenharmony_ci
141e5c31af7Sopenharmony_ci	void						clear				(void);
142e5c31af7Sopenharmony_ci
143e5c31af7Sopenharmony_ci	template<typename Y>
144e5c31af7Sopenharmony_ci	operator SharedPtr<Y>		(void) const;
145e5c31af7Sopenharmony_ci
146e5c31af7Sopenharmony_ciprivate:
147e5c31af7Sopenharmony_ci	void						acquire				(void);
148e5c31af7Sopenharmony_ci	void						acquireFromWeak		(const WeakPtr<T>& other);
149e5c31af7Sopenharmony_ci	void						release				(void);
150e5c31af7Sopenharmony_ci
151e5c31af7Sopenharmony_ci	T*							m_ptr;
152e5c31af7Sopenharmony_ci	SharedPtrStateBase*			m_state;
153e5c31af7Sopenharmony_ci
154e5c31af7Sopenharmony_ci	friend class WeakPtr<T>;
155e5c31af7Sopenharmony_ci
156e5c31af7Sopenharmony_ci	template<typename U>
157e5c31af7Sopenharmony_ci	friend class SharedPtr;
158e5c31af7Sopenharmony_ci};
159e5c31af7Sopenharmony_ci
160e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
161e5c31af7Sopenharmony_ci * \brief Weak pointer
162e5c31af7Sopenharmony_ci *
163e5c31af7Sopenharmony_ci * WeakPtr manages weak references to objects owned by SharedPtr. Shared
164e5c31af7Sopenharmony_ci * pointer can be converted to weak pointer and vice versa. Weak pointer
165e5c31af7Sopenharmony_ci * differs from SharedPtr by not affecting the lifetime of the managed
166e5c31af7Sopenharmony_ci * object.
167e5c31af7Sopenharmony_ci *
168e5c31af7Sopenharmony_ci * WeakPtr can be converted back to SharedPtr but that operation can fail
169e5c31af7Sopenharmony_ci * if the object is no longer live. In such case DeadReferenceException
170e5c31af7Sopenharmony_ci * will be thrown.
171e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
172e5c31af7Sopenharmony_citemplate<typename T>
173e5c31af7Sopenharmony_ciclass WeakPtr
174e5c31af7Sopenharmony_ci{
175e5c31af7Sopenharmony_cipublic:
176e5c31af7Sopenharmony_ci						WeakPtr		(void);
177e5c31af7Sopenharmony_ci						WeakPtr		(const WeakPtr<T>& other);
178e5c31af7Sopenharmony_ci
179e5c31af7Sopenharmony_ci	explicit			WeakPtr		(const SharedPtr<T>& other);
180e5c31af7Sopenharmony_ci						~WeakPtr	(void);
181e5c31af7Sopenharmony_ci
182e5c31af7Sopenharmony_ci	WeakPtr&			operator=	(const WeakPtr<T>& other);
183e5c31af7Sopenharmony_ci	WeakPtr&			operator=	(const SharedPtr<T>& other);
184e5c31af7Sopenharmony_ci
185e5c31af7Sopenharmony_ci	SharedPtr<T>		lock		(void);
186e5c31af7Sopenharmony_ci
187e5c31af7Sopenharmony_ciprivate:
188e5c31af7Sopenharmony_ci	void				acquire		(void);
189e5c31af7Sopenharmony_ci	void				release		(void);
190e5c31af7Sopenharmony_ci
191e5c31af7Sopenharmony_ci	T*					m_ptr;
192e5c31af7Sopenharmony_ci	SharedPtrStateBase*	m_state;
193e5c31af7Sopenharmony_ci
194e5c31af7Sopenharmony_ci	friend class SharedPtr<T>;
195e5c31af7Sopenharmony_ci};
196e5c31af7Sopenharmony_ci
197e5c31af7Sopenharmony_ci// SharedPtr template implementation.
198e5c31af7Sopenharmony_ci
199e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
200e5c31af7Sopenharmony_ci * \brief Construct empty shared pointer.
201e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
202e5c31af7Sopenharmony_citemplate<typename T>
203e5c31af7Sopenharmony_ciinline SharedPtr<T>::SharedPtr (void)
204e5c31af7Sopenharmony_ci	: m_ptr		(DE_NULL)
205e5c31af7Sopenharmony_ci	, m_state	(DE_NULL)
206e5c31af7Sopenharmony_ci{
207e5c31af7Sopenharmony_ci}
208e5c31af7Sopenharmony_ci
209e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
210e5c31af7Sopenharmony_ci * \brief Construct shared pointer from pointer.
211e5c31af7Sopenharmony_ci * \param ptr Pointer to be managed.
212e5c31af7Sopenharmony_ci *
213e5c31af7Sopenharmony_ci * Ownership of the pointer will be transferred to SharedPtr and future
214e5c31af7Sopenharmony_ci * SharedPtr's initialized or assigned from this SharedPtr.
215e5c31af7Sopenharmony_ci *
216e5c31af7Sopenharmony_ci * If allocation of shared state fails. The "ptr" argument will not be
217e5c31af7Sopenharmony_ci * released.
218e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
219e5c31af7Sopenharmony_citemplate<typename T>
220e5c31af7Sopenharmony_ciinline SharedPtr<T>::SharedPtr (T* ptr)
221e5c31af7Sopenharmony_ci	: m_ptr		(DE_NULL)
222e5c31af7Sopenharmony_ci	, m_state	(DE_NULL)
223e5c31af7Sopenharmony_ci{
224e5c31af7Sopenharmony_ci	try
225e5c31af7Sopenharmony_ci	{
226e5c31af7Sopenharmony_ci		m_ptr	= ptr;
227e5c31af7Sopenharmony_ci		m_state	= new SharedPtrState<T, DefaultDeleter<T> >(ptr, DefaultDeleter<T>());
228e5c31af7Sopenharmony_ci		m_state->strongRefCount	= 1;
229e5c31af7Sopenharmony_ci		m_state->weakRefCount	= 1;
230e5c31af7Sopenharmony_ci	}
231e5c31af7Sopenharmony_ci	catch (...)
232e5c31af7Sopenharmony_ci	{
233e5c31af7Sopenharmony_ci		// \note ptr is not released.
234e5c31af7Sopenharmony_ci		delete m_state;
235e5c31af7Sopenharmony_ci		throw;
236e5c31af7Sopenharmony_ci	}
237e5c31af7Sopenharmony_ci}
238e5c31af7Sopenharmony_ci
239e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
240e5c31af7Sopenharmony_ci * \brief Construct shared pointer from pointer.
241e5c31af7Sopenharmony_ci * \param ptr Pointer to be managed.
242e5c31af7Sopenharmony_ci *
243e5c31af7Sopenharmony_ci * Ownership of the pointer will be transferred to SharedPtr and future
244e5c31af7Sopenharmony_ci * SharedPtr's initialized or assigned from this SharedPtr.
245e5c31af7Sopenharmony_ci *
246e5c31af7Sopenharmony_ci * Deleter must be callable type and deleter is called with the pointer
247e5c31af7Sopenharmony_ci * argument when the reference count becomes 0.
248e5c31af7Sopenharmony_ci *
249e5c31af7Sopenharmony_ci * If allocation of shared state fails. The "ptr" argument will not be
250e5c31af7Sopenharmony_ci * released.
251e5c31af7Sopenharmony_ci *
252e5c31af7Sopenharmony_ci * Calling deleter or calling destructor for deleter should never throw.
253e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
254e5c31af7Sopenharmony_citemplate<typename T>
255e5c31af7Sopenharmony_citemplate<typename Deleter>
256e5c31af7Sopenharmony_ciinline SharedPtr<T>::SharedPtr (T* ptr, Deleter deleter)
257e5c31af7Sopenharmony_ci	: m_ptr		(DE_NULL)
258e5c31af7Sopenharmony_ci	, m_state	(DE_NULL)
259e5c31af7Sopenharmony_ci{
260e5c31af7Sopenharmony_ci	try
261e5c31af7Sopenharmony_ci	{
262e5c31af7Sopenharmony_ci		m_ptr	= ptr;
263e5c31af7Sopenharmony_ci		m_state	= new SharedPtrState<T, Deleter>(ptr, deleter);
264e5c31af7Sopenharmony_ci		m_state->strongRefCount	= 1;
265e5c31af7Sopenharmony_ci		m_state->weakRefCount	= 1;
266e5c31af7Sopenharmony_ci	}
267e5c31af7Sopenharmony_ci	catch (...)
268e5c31af7Sopenharmony_ci	{
269e5c31af7Sopenharmony_ci		// \note ptr is not released.
270e5c31af7Sopenharmony_ci		delete m_state;
271e5c31af7Sopenharmony_ci		throw;
272e5c31af7Sopenharmony_ci	}
273e5c31af7Sopenharmony_ci}
274e5c31af7Sopenharmony_ci
275e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
276e5c31af7Sopenharmony_ci * \brief Initialize shared pointer from another SharedPtr.
277e5c31af7Sopenharmony_ci * \param other Pointer to be shared.
278e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
279e5c31af7Sopenharmony_citemplate<typename T>
280e5c31af7Sopenharmony_ciinline SharedPtr<T>::SharedPtr (const SharedPtr<T>& other)
281e5c31af7Sopenharmony_ci	: m_ptr		(other.m_ptr)
282e5c31af7Sopenharmony_ci	, m_state	(other.m_state)
283e5c31af7Sopenharmony_ci{
284e5c31af7Sopenharmony_ci	acquire();
285e5c31af7Sopenharmony_ci}
286e5c31af7Sopenharmony_ci
287e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
288e5c31af7Sopenharmony_ci * \brief Initialize shared pointer from another SharedPtr.
289e5c31af7Sopenharmony_ci * \param other Pointer to be shared.
290e5c31af7Sopenharmony_ci *
291e5c31af7Sopenharmony_ci * Y* must be convertible to T*.
292e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
293e5c31af7Sopenharmony_citemplate<typename T>
294e5c31af7Sopenharmony_citemplate<typename Y>
295e5c31af7Sopenharmony_ciinline SharedPtr<T>::SharedPtr (const SharedPtr<Y>& other)
296e5c31af7Sopenharmony_ci	: m_ptr		(other.m_ptr)
297e5c31af7Sopenharmony_ci	, m_state	(other.m_state)
298e5c31af7Sopenharmony_ci{
299e5c31af7Sopenharmony_ci	acquire();
300e5c31af7Sopenharmony_ci}
301e5c31af7Sopenharmony_ci
302e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
303e5c31af7Sopenharmony_ci * \brief Initialize shared pointer from weak reference.
304e5c31af7Sopenharmony_ci * \param other Pointer to be shared.
305e5c31af7Sopenharmony_ci *
306e5c31af7Sopenharmony_ci * Y* must be convertible to T*.
307e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
308e5c31af7Sopenharmony_citemplate<typename T>
309e5c31af7Sopenharmony_citemplate<typename Y>
310e5c31af7Sopenharmony_ciinline SharedPtr<T>::SharedPtr (const WeakPtr<Y>& other)
311e5c31af7Sopenharmony_ci	: m_ptr		(DE_NULL)
312e5c31af7Sopenharmony_ci	, m_state	(DE_NULL)
313e5c31af7Sopenharmony_ci{
314e5c31af7Sopenharmony_ci	acquireFromWeak(other);
315e5c31af7Sopenharmony_ci}
316e5c31af7Sopenharmony_ci
317e5c31af7Sopenharmony_citemplate<typename T>
318e5c31af7Sopenharmony_ciinline SharedPtr<T>::~SharedPtr (void)
319e5c31af7Sopenharmony_ci{
320e5c31af7Sopenharmony_ci	release();
321e5c31af7Sopenharmony_ci}
322e5c31af7Sopenharmony_ci
323e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
324e5c31af7Sopenharmony_ci * \brief Assign from other shared pointer.
325e5c31af7Sopenharmony_ci * \param other Pointer to be shared.
326e5c31af7Sopenharmony_ci * \return Reference to this SharedPtr.
327e5c31af7Sopenharmony_ci *
328e5c31af7Sopenharmony_ci * Reference to current pointer is released and reference to new pointer is
329e5c31af7Sopenharmony_ci * acquired.
330e5c31af7Sopenharmony_ci *
331e5c31af7Sopenharmony_ci * Y* must be convertible to T*.
332e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
333e5c31af7Sopenharmony_citemplate<typename T>
334e5c31af7Sopenharmony_citemplate<typename Y>
335e5c31af7Sopenharmony_ciinline SharedPtr<T>& SharedPtr<T>::operator= (const SharedPtr<Y>& other)
336e5c31af7Sopenharmony_ci{
337e5c31af7Sopenharmony_ci	if (m_state == other.m_state)
338e5c31af7Sopenharmony_ci		return *this;
339e5c31af7Sopenharmony_ci
340e5c31af7Sopenharmony_ci	// Release current reference.
341e5c31af7Sopenharmony_ci	release();
342e5c31af7Sopenharmony_ci
343e5c31af7Sopenharmony_ci	// Copy from other and acquire reference.
344e5c31af7Sopenharmony_ci	m_ptr	= other.m_ptr;
345e5c31af7Sopenharmony_ci	m_state	= other.m_state;
346e5c31af7Sopenharmony_ci
347e5c31af7Sopenharmony_ci	acquire();
348e5c31af7Sopenharmony_ci
349e5c31af7Sopenharmony_ci	return *this;
350e5c31af7Sopenharmony_ci}
351e5c31af7Sopenharmony_ci
352e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
353e5c31af7Sopenharmony_ci * \brief Assign from other shared pointer.
354e5c31af7Sopenharmony_ci * \param other Pointer to be shared.
355e5c31af7Sopenharmony_ci * \return Reference to this SharedPtr.
356e5c31af7Sopenharmony_ci *
357e5c31af7Sopenharmony_ci * Reference to current pointer is released and reference to new pointer is
358e5c31af7Sopenharmony_ci * acquired.
359e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
360e5c31af7Sopenharmony_citemplate<typename T>
361e5c31af7Sopenharmony_ciinline SharedPtr<T>& SharedPtr<T>::operator= (const SharedPtr<T>& other)
362e5c31af7Sopenharmony_ci{
363e5c31af7Sopenharmony_ci	if (m_state == other.m_state)
364e5c31af7Sopenharmony_ci		return *this;
365e5c31af7Sopenharmony_ci
366e5c31af7Sopenharmony_ci	// Release current reference.
367e5c31af7Sopenharmony_ci	release();
368e5c31af7Sopenharmony_ci
369e5c31af7Sopenharmony_ci	// Copy from other and acquire reference.
370e5c31af7Sopenharmony_ci	m_ptr	= other.m_ptr;
371e5c31af7Sopenharmony_ci	m_state	= other.m_state;
372e5c31af7Sopenharmony_ci
373e5c31af7Sopenharmony_ci	acquire();
374e5c31af7Sopenharmony_ci
375e5c31af7Sopenharmony_ci	return *this;
376e5c31af7Sopenharmony_ci}
377e5c31af7Sopenharmony_ci
378e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
379e5c31af7Sopenharmony_ci * \brief Assign from weak pointer.
380e5c31af7Sopenharmony_ci * \param other Weak reference.
381e5c31af7Sopenharmony_ci * \return Reference to this SharedPtr.
382e5c31af7Sopenharmony_ci *
383e5c31af7Sopenharmony_ci * Tries to acquire reference to WeakPtr, releases current reference and
384e5c31af7Sopenharmony_ci * holds reference to new pointer.
385e5c31af7Sopenharmony_ci *
386e5c31af7Sopenharmony_ci * If WeakPtr can't be acquired, throws DeadReferenceException and doesn't
387e5c31af7Sopenharmony_ci * release the current reference.
388e5c31af7Sopenharmony_ci *
389e5c31af7Sopenharmony_ci * If WeakPtr references same pointer as SharedPtr this call will always
390e5c31af7Sopenharmony_ci * succeed.
391e5c31af7Sopenharmony_ci *
392e5c31af7Sopenharmony_ci * Y* must be convertible to T*.
393e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
394e5c31af7Sopenharmony_citemplate<typename T>
395e5c31af7Sopenharmony_citemplate<typename Y>
396e5c31af7Sopenharmony_ciinline SharedPtr<T>& SharedPtr<T>::operator= (const WeakPtr<Y>& other)
397e5c31af7Sopenharmony_ci{
398e5c31af7Sopenharmony_ci	if (m_state == other.m_state)
399e5c31af7Sopenharmony_ci		return *this;
400e5c31af7Sopenharmony_ci
401e5c31af7Sopenharmony_ci	{
402e5c31af7Sopenharmony_ci		SharedPtr<T> sharedOther(other);
403e5c31af7Sopenharmony_ci		*this = other;
404e5c31af7Sopenharmony_ci	}
405e5c31af7Sopenharmony_ci
406e5c31af7Sopenharmony_ci	return *this;
407e5c31af7Sopenharmony_ci}
408e5c31af7Sopenharmony_ci
409e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
410e5c31af7Sopenharmony_ci * \brief Type conversion operator.
411e5c31af7Sopenharmony_ci *
412e5c31af7Sopenharmony_ci * T* must be convertible to Y*.
413e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
414e5c31af7Sopenharmony_citemplate<class T>
415e5c31af7Sopenharmony_citemplate<typename Y>
416e5c31af7Sopenharmony_ciinline SharedPtr<T>::operator SharedPtr<Y> (void) const
417e5c31af7Sopenharmony_ci{
418e5c31af7Sopenharmony_ci	return SharedPtr<Y>(*this);
419e5c31af7Sopenharmony_ci}
420e5c31af7Sopenharmony_ci
421e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
422e5c31af7Sopenharmony_ci * \brief Compare pointers.
423e5c31af7Sopenharmony_ci * \param a A
424e5c31af7Sopenharmony_ci * \param b B
425e5c31af7Sopenharmony_ci * \return true if A and B point to same object, false otherwise.
426e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
427e5c31af7Sopenharmony_citemplate<class T, class U>
428e5c31af7Sopenharmony_ciinline bool operator== (const SharedPtr<T>& a, const SharedPtr<U>& b) throw()
429e5c31af7Sopenharmony_ci{
430e5c31af7Sopenharmony_ci	return a.get() == b.get();
431e5c31af7Sopenharmony_ci}
432e5c31af7Sopenharmony_ci
433e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
434e5c31af7Sopenharmony_ci * \brief Compare pointers.
435e5c31af7Sopenharmony_ci * \param a A
436e5c31af7Sopenharmony_ci * \param b B
437e5c31af7Sopenharmony_ci * \return true if A and B point to different objects, false otherwise.
438e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
439e5c31af7Sopenharmony_citemplate<class T, class U>
440e5c31af7Sopenharmony_ciinline bool operator!= (const SharedPtr<T>& a, const SharedPtr<U>& b) throw()
441e5c31af7Sopenharmony_ci{
442e5c31af7Sopenharmony_ci	return a.get() != b.get();
443e5c31af7Sopenharmony_ci}
444e5c31af7Sopenharmony_ci
445e5c31af7Sopenharmony_ci/** Swap pointer contents. */
446e5c31af7Sopenharmony_citemplate<typename T>
447e5c31af7Sopenharmony_ciinline void SharedPtr<T>::swap (SharedPtr<T>& other)
448e5c31af7Sopenharmony_ci{
449e5c31af7Sopenharmony_ci	using std::swap;
450e5c31af7Sopenharmony_ci	swap(m_ptr,		other.m_ptr);
451e5c31af7Sopenharmony_ci	swap(m_state,	other.m_state);
452e5c31af7Sopenharmony_ci}
453e5c31af7Sopenharmony_ci
454e5c31af7Sopenharmony_ci/** Swap operator for SharedPtr's. */
455e5c31af7Sopenharmony_citemplate<typename T>
456e5c31af7Sopenharmony_ciinline void swap (SharedPtr<T>& a, SharedPtr<T>& b)
457e5c31af7Sopenharmony_ci{
458e5c31af7Sopenharmony_ci	a.swap(b);
459e5c31af7Sopenharmony_ci}
460e5c31af7Sopenharmony_ci
461e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
462e5c31af7Sopenharmony_ci * \brief Set pointer to null.
463e5c31af7Sopenharmony_ci *
464e5c31af7Sopenharmony_ci * clear() removes current reference and sets pointer to null value.
465e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
466e5c31af7Sopenharmony_citemplate<typename T>
467e5c31af7Sopenharmony_ciinline void SharedPtr<T>::clear (void)
468e5c31af7Sopenharmony_ci{
469e5c31af7Sopenharmony_ci	release();
470e5c31af7Sopenharmony_ci	m_ptr	= DE_NULL;
471e5c31af7Sopenharmony_ci	m_state	= DE_NULL;
472e5c31af7Sopenharmony_ci}
473e5c31af7Sopenharmony_ci
474e5c31af7Sopenharmony_citemplate<typename T>
475e5c31af7Sopenharmony_ciinline void SharedPtr<T>::acquireFromWeak (const WeakPtr<T>& weakRef)
476e5c31af7Sopenharmony_ci{
477e5c31af7Sopenharmony_ci	DE_ASSERT(!m_ptr && !m_state);
478e5c31af7Sopenharmony_ci
479e5c31af7Sopenharmony_ci	SharedPtrStateBase* state = weakRef.m_state;
480e5c31af7Sopenharmony_ci
481e5c31af7Sopenharmony_ci	if (!state)
482e5c31af7Sopenharmony_ci		return; // Empty reference.
483e5c31af7Sopenharmony_ci
484e5c31af7Sopenharmony_ci	{
485e5c31af7Sopenharmony_ci		deInt32 oldCount, newCount;
486e5c31af7Sopenharmony_ci
487e5c31af7Sopenharmony_ci		// Do atomic compare and increment.
488e5c31af7Sopenharmony_ci		do
489e5c31af7Sopenharmony_ci		{
490e5c31af7Sopenharmony_ci			oldCount = state->strongRefCount;
491e5c31af7Sopenharmony_ci			if (oldCount == 0)
492e5c31af7Sopenharmony_ci				throw DeadReferenceException();
493e5c31af7Sopenharmony_ci			newCount = oldCount+1;
494e5c31af7Sopenharmony_ci		} while (deAtomicCompareExchange32((deUint32 volatile*)&state->strongRefCount, (deUint32)oldCount, (deUint32)newCount) != (deUint32)oldCount);
495e5c31af7Sopenharmony_ci
496e5c31af7Sopenharmony_ci		deAtomicIncrement32(&state->weakRefCount);
497e5c31af7Sopenharmony_ci	}
498e5c31af7Sopenharmony_ci
499e5c31af7Sopenharmony_ci	m_ptr	= weakRef.m_ptr;
500e5c31af7Sopenharmony_ci	m_state	= state;
501e5c31af7Sopenharmony_ci}
502e5c31af7Sopenharmony_ci
503e5c31af7Sopenharmony_citemplate<typename T>
504e5c31af7Sopenharmony_ciinline void SharedPtr<T>::acquire (void)
505e5c31af7Sopenharmony_ci{
506e5c31af7Sopenharmony_ci	if (m_state)
507e5c31af7Sopenharmony_ci	{
508e5c31af7Sopenharmony_ci		deAtomicIncrement32(&m_state->strongRefCount);
509e5c31af7Sopenharmony_ci		deAtomicIncrement32(&m_state->weakRefCount);
510e5c31af7Sopenharmony_ci	}
511e5c31af7Sopenharmony_ci}
512e5c31af7Sopenharmony_ci
513e5c31af7Sopenharmony_citemplate<typename T>
514e5c31af7Sopenharmony_ciinline void SharedPtr<T>::release (void)
515e5c31af7Sopenharmony_ci{
516e5c31af7Sopenharmony_ci	if (m_state)
517e5c31af7Sopenharmony_ci	{
518e5c31af7Sopenharmony_ci		if (deAtomicDecrement32(&m_state->strongRefCount) == 0)
519e5c31af7Sopenharmony_ci		{
520e5c31af7Sopenharmony_ci			m_ptr = DE_NULL;
521e5c31af7Sopenharmony_ci			m_state->deletePtr();
522e5c31af7Sopenharmony_ci		}
523e5c31af7Sopenharmony_ci
524e5c31af7Sopenharmony_ci		if (deAtomicDecrement32(&m_state->weakRefCount) == 0)
525e5c31af7Sopenharmony_ci		{
526e5c31af7Sopenharmony_ci			delete m_state;
527e5c31af7Sopenharmony_ci			m_state = DE_NULL;
528e5c31af7Sopenharmony_ci		}
529e5c31af7Sopenharmony_ci	}
530e5c31af7Sopenharmony_ci}
531e5c31af7Sopenharmony_ci
532e5c31af7Sopenharmony_ci// WeakPtr template implementation.
533e5c31af7Sopenharmony_ci
534e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
535e5c31af7Sopenharmony_ci * \brief Construct empty weak pointer.
536e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
537e5c31af7Sopenharmony_citemplate<typename T>
538e5c31af7Sopenharmony_ciinline WeakPtr<T>::WeakPtr (void)
539e5c31af7Sopenharmony_ci	: m_ptr		(DE_NULL)
540e5c31af7Sopenharmony_ci	, m_state	(DE_NULL)
541e5c31af7Sopenharmony_ci{
542e5c31af7Sopenharmony_ci}
543e5c31af7Sopenharmony_ci
544e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
545e5c31af7Sopenharmony_ci * \brief Construct weak pointer from other weak reference.
546e5c31af7Sopenharmony_ci * \param other Weak reference.
547e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
548e5c31af7Sopenharmony_citemplate<typename T>
549e5c31af7Sopenharmony_ciinline WeakPtr<T>::WeakPtr (const WeakPtr<T>& other)
550e5c31af7Sopenharmony_ci	: m_ptr		(other.m_ptr)
551e5c31af7Sopenharmony_ci	, m_state	(other.m_state)
552e5c31af7Sopenharmony_ci{
553e5c31af7Sopenharmony_ci	acquire();
554e5c31af7Sopenharmony_ci}
555e5c31af7Sopenharmony_ci
556e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
557e5c31af7Sopenharmony_ci * \brief Construct weak pointer from shared pointer.
558e5c31af7Sopenharmony_ci * \param other Shared pointer.
559e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
560e5c31af7Sopenharmony_citemplate<typename T>
561e5c31af7Sopenharmony_ciinline WeakPtr<T>::WeakPtr (const SharedPtr<T>& other)
562e5c31af7Sopenharmony_ci	: m_ptr		(other.m_ptr)
563e5c31af7Sopenharmony_ci	, m_state	(other.m_state)
564e5c31af7Sopenharmony_ci{
565e5c31af7Sopenharmony_ci	acquire();
566e5c31af7Sopenharmony_ci}
567e5c31af7Sopenharmony_ci
568e5c31af7Sopenharmony_citemplate<typename T>
569e5c31af7Sopenharmony_ciinline WeakPtr<T>::~WeakPtr (void)
570e5c31af7Sopenharmony_ci{
571e5c31af7Sopenharmony_ci	release();
572e5c31af7Sopenharmony_ci}
573e5c31af7Sopenharmony_ci
574e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
575e5c31af7Sopenharmony_ci * \brief Assign from another weak pointer.
576e5c31af7Sopenharmony_ci * \param other Weak reference.
577e5c31af7Sopenharmony_ci * \return Reference to this WeakPtr.
578e5c31af7Sopenharmony_ci *
579e5c31af7Sopenharmony_ci * The current weak reference is removed first and then a new weak reference
580e5c31af7Sopenharmony_ci * to the object pointed by other is taken.
581e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
582e5c31af7Sopenharmony_citemplate<typename T>
583e5c31af7Sopenharmony_ciinline WeakPtr<T>& WeakPtr<T>::operator= (const WeakPtr<T>& other)
584e5c31af7Sopenharmony_ci{
585e5c31af7Sopenharmony_ci	if (this == &other)
586e5c31af7Sopenharmony_ci		return *this;
587e5c31af7Sopenharmony_ci
588e5c31af7Sopenharmony_ci	release();
589e5c31af7Sopenharmony_ci
590e5c31af7Sopenharmony_ci	m_ptr	= other.m_ptr;
591e5c31af7Sopenharmony_ci	m_state	= other.m_state;
592e5c31af7Sopenharmony_ci
593e5c31af7Sopenharmony_ci	acquire();
594e5c31af7Sopenharmony_ci
595e5c31af7Sopenharmony_ci	return *this;
596e5c31af7Sopenharmony_ci}
597e5c31af7Sopenharmony_ci
598e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
599e5c31af7Sopenharmony_ci * \brief Assign from shared pointer.
600e5c31af7Sopenharmony_ci * \param other Shared pointer.
601e5c31af7Sopenharmony_ci * \return Reference to this WeakPtr.
602e5c31af7Sopenharmony_ci *
603e5c31af7Sopenharmony_ci * The current weak reference is removed first and then a new weak reference
604e5c31af7Sopenharmony_ci * to the object pointed by other is taken.
605e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
606e5c31af7Sopenharmony_citemplate<typename T>
607e5c31af7Sopenharmony_ciinline WeakPtr<T>& WeakPtr<T>::operator= (const SharedPtr<T>& other)
608e5c31af7Sopenharmony_ci{
609e5c31af7Sopenharmony_ci	release();
610e5c31af7Sopenharmony_ci
611e5c31af7Sopenharmony_ci	m_ptr	= other.m_ptr;
612e5c31af7Sopenharmony_ci	m_state	= other.m_state;
613e5c31af7Sopenharmony_ci
614e5c31af7Sopenharmony_ci	acquire();
615e5c31af7Sopenharmony_ci
616e5c31af7Sopenharmony_ci	return *this;
617e5c31af7Sopenharmony_ci}
618e5c31af7Sopenharmony_ci
619e5c31af7Sopenharmony_citemplate<typename T>
620e5c31af7Sopenharmony_ciinline void WeakPtr<T>::acquire (void)
621e5c31af7Sopenharmony_ci{
622e5c31af7Sopenharmony_ci	if (m_state)
623e5c31af7Sopenharmony_ci		deAtomicIncrement32(&m_state->weakRefCount);
624e5c31af7Sopenharmony_ci}
625e5c31af7Sopenharmony_ci
626e5c31af7Sopenharmony_citemplate<typename T>
627e5c31af7Sopenharmony_ciinline void WeakPtr<T>::release (void)
628e5c31af7Sopenharmony_ci{
629e5c31af7Sopenharmony_ci	if (m_state)
630e5c31af7Sopenharmony_ci	{
631e5c31af7Sopenharmony_ci		if (deAtomicDecrement32(&m_state->weakRefCount) == 0)
632e5c31af7Sopenharmony_ci		{
633e5c31af7Sopenharmony_ci			delete m_state;
634e5c31af7Sopenharmony_ci			m_state	= DE_NULL;
635e5c31af7Sopenharmony_ci			m_ptr	= DE_NULL;
636e5c31af7Sopenharmony_ci		}
637e5c31af7Sopenharmony_ci	}
638e5c31af7Sopenharmony_ci}
639e5c31af7Sopenharmony_ci
640e5c31af7Sopenharmony_ci} // de
641e5c31af7Sopenharmony_ci
642e5c31af7Sopenharmony_ci#endif // _DESHAREDPTR_HPP
643