13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifndef _DESHAREDPTR_HPP
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define _DESHAREDPTR_HPP
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements C++ Base Library
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -----------------------------
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Shared pointer.
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deDefs.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deAtomic.h"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <exception>
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <algorithm>
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace de
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Shared pointer self-test.
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid SharedPtr_selfTest (void);
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass DeadReferenceException : public std::exception
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
416801c0680107ff001b065db07b125d622926f311Mika Isojärvi				DeadReferenceException	(void) throw()
426801c0680107ff001b065db07b125d622926f311Mika Isojärvi		: std::exception()
436801c0680107ff001b065db07b125d622926f311Mika Isojärvi	{
446801c0680107ff001b065db07b125d622926f311Mika Isojärvi	}
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
466801c0680107ff001b065db07b125d622926f311Mika Isojärvi	const char*	what					(void) const throw()
476801c0680107ff001b065db07b125d622926f311Mika Isojärvi	{
486801c0680107ff001b065db07b125d622926f311Mika Isojärvi		return "DeadReferenceException";
496801c0680107ff001b065db07b125d622926f311Mika Isojärvi	}
506801c0680107ff001b065db07b125d622926f311Mika Isojärvi};
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
526801c0680107ff001b065db07b125d622926f311Mika Isojärvistruct SharedPtrStateBase
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
546801c0680107ff001b065db07b125d622926f311Mika Isojärvi	SharedPtrStateBase (void)
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: strongRefCount	(0)
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, weakRefCount		(0)
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
606801c0680107ff001b065db07b125d622926f311Mika Isojärvi	virtual				~SharedPtrStateBase	(void) throw() {}
616801c0680107ff001b065db07b125d622926f311Mika Isojärvi	virtual void		deletePtr			(void) throw() = 0;
626801c0680107ff001b065db07b125d622926f311Mika Isojärvi
636801c0680107ff001b065db07b125d622926f311Mika Isojärvi	volatile deInt32	strongRefCount;
646801c0680107ff001b065db07b125d622926f311Mika Isojärvi	volatile deInt32	weakRefCount;		//!< WeakPtr references + StrongPtr references.
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
676801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename Type, typename Deleter>
686801c0680107ff001b065db07b125d622926f311Mika Isojärvistruct SharedPtrState : public SharedPtrStateBase
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
706801c0680107ff001b065db07b125d622926f311Mika Isojärvi	SharedPtrState (Type* ptr, Deleter deleter)
716801c0680107ff001b065db07b125d622926f311Mika Isojärvi		: m_ptr		(ptr)
726801c0680107ff001b065db07b125d622926f311Mika Isojärvi		, m_deleter	(deleter)
736801c0680107ff001b065db07b125d622926f311Mika Isojärvi	{
746801c0680107ff001b065db07b125d622926f311Mika Isojärvi	}
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
766801c0680107ff001b065db07b125d622926f311Mika Isojärvi	virtual ~SharedPtrState (void) throw()
776801c0680107ff001b065db07b125d622926f311Mika Isojärvi	{
786801c0680107ff001b065db07b125d622926f311Mika Isojärvi		DE_ASSERT(!m_ptr);
796801c0680107ff001b065db07b125d622926f311Mika Isojärvi	}
806801c0680107ff001b065db07b125d622926f311Mika Isojärvi
816801c0680107ff001b065db07b125d622926f311Mika Isojärvi	virtual void deletePtr (void) throw()
826801c0680107ff001b065db07b125d622926f311Mika Isojärvi	{
836801c0680107ff001b065db07b125d622926f311Mika Isojärvi		m_deleter(m_ptr);
846801c0680107ff001b065db07b125d622926f311Mika Isojärvi		m_ptr = DE_NULL;
856801c0680107ff001b065db07b125d622926f311Mika Isojärvi	}
866801c0680107ff001b065db07b125d622926f311Mika Isojärvi
876801c0680107ff001b065db07b125d622926f311Mika Isojärviprivate:
886801c0680107ff001b065db07b125d622926f311Mika Isojärvi	Type*		m_ptr;
896801c0680107ff001b065db07b125d622926f311Mika Isojärvi	Deleter		m_deleter;
906801c0680107ff001b065db07b125d622926f311Mika Isojärvi};
916801c0680107ff001b065db07b125d622926f311Mika Isojärvi
926801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SharedPtr;
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
956801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass WeakPtr;
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Shared pointer
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * SharedPtr is smart pointer for managing shared ownership to a pointer.
1026801c0680107ff001b065db07b125d622926f311Mika Isojärvi * Multiple SharedPtrs can maintain ownership to the pointer and it is
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * destructed when last SharedPtr is destroyed.
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
1056801c0680107ff001b065db07b125d622926f311Mika Isojärvi * SharedPtr can also be NULL.
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
1076801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SharedPtr
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								SharedPtr			(void);
1126801c0680107ff001b065db07b125d622926f311Mika Isojärvi								SharedPtr			(const SharedPtr<T>& other);
1136801c0680107ff001b065db07b125d622926f311Mika Isojärvi	explicit					SharedPtr			(T* ptr);
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1156801c0680107ff001b065db07b125d622926f311Mika Isojärvi	template<typename Deleter>
1166801c0680107ff001b065db07b125d622926f311Mika Isojärvi								SharedPtr			(T* ptr, Deleter deleter);
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1186801c0680107ff001b065db07b125d622926f311Mika Isojärvi	template<typename Y>
1196801c0680107ff001b065db07b125d622926f311Mika Isojärvi	explicit					SharedPtr			(const SharedPtr<Y>& other);
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1216801c0680107ff001b065db07b125d622926f311Mika Isojärvi	template<typename Y>
1226801c0680107ff001b065db07b125d622926f311Mika Isojärvi	explicit					SharedPtr			(const WeakPtr<Y>& other);
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								~SharedPtr			(void);
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1266801c0680107ff001b065db07b125d622926f311Mika Isojärvi	template<typename Y>
1276801c0680107ff001b065db07b125d622926f311Mika Isojärvi	SharedPtr&					operator=			(const SharedPtr<Y>& other);
1286801c0680107ff001b065db07b125d622926f311Mika Isojärvi	SharedPtr&					operator=			(const SharedPtr<T>& other);
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1306801c0680107ff001b065db07b125d622926f311Mika Isojärvi	template<typename Y>
1316801c0680107ff001b065db07b125d622926f311Mika Isojärvi	SharedPtr&					operator=			(const WeakPtr<Y>& other);
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	T*							get					(void) const throw() { return m_ptr;	}	//!< Get stored pointer.
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	T*							operator->			(void) const throw() { return m_ptr;	}	//!< Get stored pointer.
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	T&							operator*			(void) const throw() { return *m_ptr;	}	//!< De-reference pointer.
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	operator					bool				(void) const throw() { return !!m_ptr;	}
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1396801c0680107ff001b065db07b125d622926f311Mika Isojärvi	void						swap				(SharedPtr<T>& other);
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						clear				(void);
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1436801c0680107ff001b065db07b125d622926f311Mika Isojärvi	template<typename Y>
1446801c0680107ff001b065db07b125d622926f311Mika Isojärvi	operator SharedPtr<Y>		(void) const;
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						acquire				(void);
1486801c0680107ff001b065db07b125d622926f311Mika Isojärvi	void						acquireFromWeak		(const WeakPtr<T>& other);
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						release				(void);
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1516801c0680107ff001b065db07b125d622926f311Mika Isojärvi	T*							m_ptr;
1526801c0680107ff001b065db07b125d622926f311Mika Isojärvi	SharedPtrStateBase*			m_state;
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1546801c0680107ff001b065db07b125d622926f311Mika Isojärvi	friend class WeakPtr<T>;
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1566801c0680107ff001b065db07b125d622926f311Mika Isojärvi	template<typename U>
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	friend class SharedPtr;
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Weak pointer
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WeakPtr manages weak references to objects owned by SharedPtr. Shared
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * pointer can be converted to weak pointer and vice versa. Weak pointer
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * differs from SharedPtr by not affecting the lifetime of the managed
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * object.
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WeakPtr can be converted back to SharedPtr but that operation can fail
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * if the object is no longer live. In such case DeadReferenceException
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * will be thrown.
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
1726801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass WeakPtr
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1766801c0680107ff001b065db07b125d622926f311Mika Isojärvi						WeakPtr		(void);
1776801c0680107ff001b065db07b125d622926f311Mika Isojärvi						WeakPtr		(const WeakPtr<T>& other);
1786801c0680107ff001b065db07b125d622926f311Mika Isojärvi
1796801c0680107ff001b065db07b125d622926f311Mika Isojärvi	explicit			WeakPtr		(const SharedPtr<T>& other);
1806801c0680107ff001b065db07b125d622926f311Mika Isojärvi						~WeakPtr	(void);
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1826801c0680107ff001b065db07b125d622926f311Mika Isojärvi	WeakPtr&			operator=	(const WeakPtr<T>& other);
1836801c0680107ff001b065db07b125d622926f311Mika Isojärvi	WeakPtr&			operator=	(const SharedPtr<T>& other);
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1856801c0680107ff001b065db07b125d622926f311Mika Isojärvi	SharedPtr<T>		lock		(void);
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1886801c0680107ff001b065db07b125d622926f311Mika Isojärvi	void				acquire		(void);
1896801c0680107ff001b065db07b125d622926f311Mika Isojärvi	void				release		(void);
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1916801c0680107ff001b065db07b125d622926f311Mika Isojärvi	T*					m_ptr;
1926801c0680107ff001b065db07b125d622926f311Mika Isojärvi	SharedPtrStateBase*	m_state;
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1946801c0680107ff001b065db07b125d622926f311Mika Isojärvi	friend class SharedPtr<T>;
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// SharedPtr template implementation.
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Construct empty shared pointer.
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
2026801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
2036801c0680107ff001b065db07b125d622926f311Mika Isojärviinline SharedPtr<T>::SharedPtr (void)
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_ptr		(DE_NULL)
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_state	(DE_NULL)
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Construct shared pointer from pointer.
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param ptr Pointer to be managed.
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Ownership of the pointer will be transferred to SharedPtr and future
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * SharedPtr's initialized or assigned from this SharedPtr.
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
2166801c0680107ff001b065db07b125d622926f311Mika Isojärvi * If allocation of shared state fails. The "ptr" argument will not be
2176801c0680107ff001b065db07b125d622926f311Mika Isojärvi * released.
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
2196801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
2206801c0680107ff001b065db07b125d622926f311Mika Isojärviinline SharedPtr<T>::SharedPtr (T* ptr)
2216801c0680107ff001b065db07b125d622926f311Mika Isojärvi	: m_ptr		(DE_NULL)
2226801c0680107ff001b065db07b125d622926f311Mika Isojärvi	, m_state	(DE_NULL)
2236801c0680107ff001b065db07b125d622926f311Mika Isojärvi{
2246801c0680107ff001b065db07b125d622926f311Mika Isojärvi	try
2256801c0680107ff001b065db07b125d622926f311Mika Isojärvi	{
2266801c0680107ff001b065db07b125d622926f311Mika Isojärvi		m_ptr	= ptr;
2276801c0680107ff001b065db07b125d622926f311Mika Isojärvi		m_state	= new SharedPtrState<T, DefaultDeleter<T> >(ptr, DefaultDeleter<T>());
2286801c0680107ff001b065db07b125d622926f311Mika Isojärvi		m_state->strongRefCount	= 1;
2296801c0680107ff001b065db07b125d622926f311Mika Isojärvi		m_state->weakRefCount	= 1;
2306801c0680107ff001b065db07b125d622926f311Mika Isojärvi	}
2316801c0680107ff001b065db07b125d622926f311Mika Isojärvi	catch (...)
2326801c0680107ff001b065db07b125d622926f311Mika Isojärvi	{
2336801c0680107ff001b065db07b125d622926f311Mika Isojärvi		// \note ptr is not released.
2346801c0680107ff001b065db07b125d622926f311Mika Isojärvi		delete m_state;
2356801c0680107ff001b065db07b125d622926f311Mika Isojärvi		throw;
2366801c0680107ff001b065db07b125d622926f311Mika Isojärvi	}
2376801c0680107ff001b065db07b125d622926f311Mika Isojärvi}
2386801c0680107ff001b065db07b125d622926f311Mika Isojärvi
2396801c0680107ff001b065db07b125d622926f311Mika Isojärvi/*--------------------------------------------------------------------*//*!
2406801c0680107ff001b065db07b125d622926f311Mika Isojärvi * \brief Construct shared pointer from pointer.
2416801c0680107ff001b065db07b125d622926f311Mika Isojärvi * \param ptr Pointer to be managed.
2426801c0680107ff001b065db07b125d622926f311Mika Isojärvi *
2436801c0680107ff001b065db07b125d622926f311Mika Isojärvi * Ownership of the pointer will be transferred to SharedPtr and future
2446801c0680107ff001b065db07b125d622926f311Mika Isojärvi * SharedPtr's initialized or assigned from this SharedPtr.
2456801c0680107ff001b065db07b125d622926f311Mika Isojärvi *
2466801c0680107ff001b065db07b125d622926f311Mika Isojärvi * Deleter must be callable type and deleter is called with the pointer
2476801c0680107ff001b065db07b125d622926f311Mika Isojärvi * argument when the reference count becomes 0.
2486801c0680107ff001b065db07b125d622926f311Mika Isojärvi *
2496801c0680107ff001b065db07b125d622926f311Mika Isojärvi * If allocation of shared state fails. The "ptr" argument will not be
2506801c0680107ff001b065db07b125d622926f311Mika Isojärvi * released.
2516801c0680107ff001b065db07b125d622926f311Mika Isojärvi *
2526801c0680107ff001b065db07b125d622926f311Mika Isojärvi * Calling deleter or calling destructor for deleter should never throw.
2536801c0680107ff001b065db07b125d622926f311Mika Isojärvi *//*--------------------------------------------------------------------*/
2546801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
2556801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename Deleter>
2566801c0680107ff001b065db07b125d622926f311Mika Isojärviinline SharedPtr<T>::SharedPtr (T* ptr, Deleter deleter)
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_ptr		(DE_NULL)
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_state	(DE_NULL)
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_ptr	= ptr;
2636801c0680107ff001b065db07b125d622926f311Mika Isojärvi		m_state	= new SharedPtrState<T, Deleter>(ptr, deleter);
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_state->strongRefCount	= 1;
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_state->weakRefCount	= 1;
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (...)
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2696801c0680107ff001b065db07b125d622926f311Mika Isojärvi		// \note ptr is not released.
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete m_state;
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw;
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Initialize shared pointer from another SharedPtr.
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param other Pointer to be shared.
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
2796801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
2806801c0680107ff001b065db07b125d622926f311Mika Isojärviinline SharedPtr<T>::SharedPtr (const SharedPtr<T>& other)
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_ptr		(other.m_ptr)
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_state	(other.m_state)
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	acquire();
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Initialize shared pointer from another SharedPtr.
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param other Pointer to be shared.
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Y* must be convertible to T*.
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
2936801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
2946801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename Y>
2956801c0680107ff001b065db07b125d622926f311Mika Isojärviinline SharedPtr<T>::SharedPtr (const SharedPtr<Y>& other)
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_ptr		(other.m_ptr)
2976801c0680107ff001b065db07b125d622926f311Mika Isojärvi	, m_state	(other.m_state)
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	acquire();
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Initialize shared pointer from weak reference.
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param other Pointer to be shared.
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Y* must be convertible to T*.
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
3086801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
3096801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename Y>
3106801c0680107ff001b065db07b125d622926f311Mika Isojärviinline SharedPtr<T>::SharedPtr (const WeakPtr<Y>& other)
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_ptr		(DE_NULL)
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_state	(DE_NULL)
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	acquireFromWeak(other);
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3176801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
3186801c0680107ff001b065db07b125d622926f311Mika Isojärviinline SharedPtr<T>::~SharedPtr (void)
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	release();
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Assign from other shared pointer.
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param other Pointer to be shared.
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return Reference to this SharedPtr.
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
3286801c0680107ff001b065db07b125d622926f311Mika Isojärvi * Reference to current pointer is released and reference to new pointer is
3296801c0680107ff001b065db07b125d622926f311Mika Isojärvi * acquired.
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Y* must be convertible to T*.
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
3336801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
3346801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename Y>
3356801c0680107ff001b065db07b125d622926f311Mika Isojärviinline SharedPtr<T>& SharedPtr<T>::operator= (const SharedPtr<Y>& other)
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3376801c0680107ff001b065db07b125d622926f311Mika Isojärvi	if (m_state == other.m_state)
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return *this;
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Release current reference.
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	release();
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Copy from other and acquire reference.
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_ptr	= other.m_ptr;
3456801c0680107ff001b065db07b125d622926f311Mika Isojärvi	m_state	= other.m_state;
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	acquire();
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return *this;
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Assign from other shared pointer.
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param other Pointer to be shared.
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return Reference to this SharedPtr.
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
3576801c0680107ff001b065db07b125d622926f311Mika Isojärvi * Reference to current pointer is released and reference to new pointer is
3586801c0680107ff001b065db07b125d622926f311Mika Isojärvi * acquired.
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
3606801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
3616801c0680107ff001b065db07b125d622926f311Mika Isojärviinline SharedPtr<T>& SharedPtr<T>::operator= (const SharedPtr<T>& other)
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3636801c0680107ff001b065db07b125d622926f311Mika Isojärvi	if (m_state == other.m_state)
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return *this;
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Release current reference.
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	release();
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Copy from other and acquire reference.
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_ptr	= other.m_ptr;
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_state	= other.m_state;
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	acquire();
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return *this;
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Assign from weak pointer.
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param other Weak reference.
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return Reference to this SharedPtr.
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
3836801c0680107ff001b065db07b125d622926f311Mika Isojärvi * Tries to acquire reference to WeakPtr, releases current reference and
3846801c0680107ff001b065db07b125d622926f311Mika Isojärvi * holds reference to new pointer.
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
3866801c0680107ff001b065db07b125d622926f311Mika Isojärvi * If WeakPtr can't be acquired, throws DeadReferenceException and doesn't
3876801c0680107ff001b065db07b125d622926f311Mika Isojärvi * release the current reference.
3886801c0680107ff001b065db07b125d622926f311Mika Isojärvi *
3896801c0680107ff001b065db07b125d622926f311Mika Isojärvi * If WeakPtr references same pointer as SharedPtr this call will always
3906801c0680107ff001b065db07b125d622926f311Mika Isojärvi * succeed.
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Y* must be convertible to T*.
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
3946801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
3956801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename Y>
3966801c0680107ff001b065db07b125d622926f311Mika Isojärviinline SharedPtr<T>& SharedPtr<T>::operator= (const WeakPtr<Y>& other)
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3986801c0680107ff001b065db07b125d622926f311Mika Isojärvi	if (m_state == other.m_state)
3996801c0680107ff001b065db07b125d622926f311Mika Isojärvi		return *this;
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4016801c0680107ff001b065db07b125d622926f311Mika Isojärvi	{
4026801c0680107ff001b065db07b125d622926f311Mika Isojärvi		SharedPtr<T> sharedOther(other);
4036801c0680107ff001b065db07b125d622926f311Mika Isojärvi		*this = other;
4046801c0680107ff001b065db07b125d622926f311Mika Isojärvi	}
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return *this;
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Type conversion operator.
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
4126801c0680107ff001b065db07b125d622926f311Mika Isojärvi * T* must be convertible to Y*.
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
4146801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<class T>
4156801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename Y>
4166801c0680107ff001b065db07b125d622926f311Mika Isojärviinline SharedPtr<T>::operator SharedPtr<Y> (void) const
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4186801c0680107ff001b065db07b125d622926f311Mika Isojärvi	return SharedPtr<Y>(*this);
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Compare pointers.
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param a A
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param b B
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return true if A and B point to same object, false otherwise.
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
4276801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<class T, class U>
4286801c0680107ff001b065db07b125d622926f311Mika Isojärviinline bool operator== (const SharedPtr<T>& a, const SharedPtr<U>& b) throw()
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return a.get() == b.get();
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Compare pointers.
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param a A
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param b B
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return true if A and B point to different objects, false otherwise.
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
4396801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<class T, class U>
4406801c0680107ff001b065db07b125d622926f311Mika Isojärviinline bool operator!= (const SharedPtr<T>& a, const SharedPtr<U>& b) throw()
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return a.get() != b.get();
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/** Swap pointer contents. */
4466801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
4476801c0680107ff001b065db07b125d622926f311Mika Isojärviinline void SharedPtr<T>::swap (SharedPtr<T>& other)
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using std::swap;
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	swap(m_ptr,		other.m_ptr);
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	swap(m_state,	other.m_state);
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/** Swap operator for SharedPtr's. */
4556801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
4566801c0680107ff001b065db07b125d622926f311Mika Isojärviinline void swap (SharedPtr<T>& a, SharedPtr<T>& b)
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	a.swap(b);
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Set pointer to null.
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * clear() removes current reference and sets pointer to null value.
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
4666801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
4676801c0680107ff001b065db07b125d622926f311Mika Isojärviinline void SharedPtr<T>::clear (void)
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	release();
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_ptr	= DE_NULL;
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_state	= DE_NULL;
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4746801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
4756801c0680107ff001b065db07b125d622926f311Mika Isojärviinline void SharedPtr<T>::acquireFromWeak (const WeakPtr<T>& weakRef)
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!m_ptr && !m_state);
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4796801c0680107ff001b065db07b125d622926f311Mika Isojärvi	SharedPtrStateBase* state = weakRef.m_state;
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!state)
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return; // Empty reference.
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4856801c0680107ff001b065db07b125d622926f311Mika Isojärvi		deInt32 oldCount, newCount;
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Do atomic compare and increment.
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		do
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			oldCount = state->strongRefCount;
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (oldCount == 0)
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw DeadReferenceException();
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			newCount = oldCount+1;
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		} while (deAtomicCompareExchange32((deUint32 volatile*)&state->strongRefCount, (deUint32)oldCount, (deUint32)newCount) != (deUint32)oldCount);
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deAtomicIncrement32(&state->weakRefCount);
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_ptr	= weakRef.m_ptr;
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_state	= state;
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5036801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
5046801c0680107ff001b065db07b125d622926f311Mika Isojärviinline void SharedPtr<T>::acquire (void)
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_state)
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5086801c0680107ff001b065db07b125d622926f311Mika Isojärvi		deAtomicIncrement32(&m_state->strongRefCount);
5096801c0680107ff001b065db07b125d622926f311Mika Isojärvi		deAtomicIncrement32(&m_state->weakRefCount);
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5136801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
5146801c0680107ff001b065db07b125d622926f311Mika Isojärviinline void SharedPtr<T>::release (void)
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_state)
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5186801c0680107ff001b065db07b125d622926f311Mika Isojärvi		if (deAtomicDecrement32(&m_state->strongRefCount) == 0)
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5206801c0680107ff001b065db07b125d622926f311Mika Isojärvi			m_ptr = DE_NULL;
5216801c0680107ff001b065db07b125d622926f311Mika Isojärvi			m_state->deletePtr();
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5236801c0680107ff001b065db07b125d622926f311Mika Isojärvi
5246801c0680107ff001b065db07b125d622926f311Mika Isojärvi		if (deAtomicDecrement32(&m_state->weakRefCount) == 0)
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5266801c0680107ff001b065db07b125d622926f311Mika Isojärvi			delete m_state;
5276801c0680107ff001b065db07b125d622926f311Mika Isojärvi			m_state = DE_NULL;
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// WeakPtr template implementation.
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Construct empty weak pointer.
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
5376801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
5386801c0680107ff001b065db07b125d622926f311Mika Isojärviinline WeakPtr<T>::WeakPtr (void)
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_ptr		(DE_NULL)
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_state	(DE_NULL)
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Construct weak pointer from other weak reference.
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param other Weak reference.
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
5486801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
5496801c0680107ff001b065db07b125d622926f311Mika Isojärviinline WeakPtr<T>::WeakPtr (const WeakPtr<T>& other)
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_ptr		(other.m_ptr)
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_state	(other.m_state)
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	acquire();
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Construct weak pointer from shared pointer.
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param other Shared pointer.
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
5606801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
5616801c0680107ff001b065db07b125d622926f311Mika Isojärviinline WeakPtr<T>::WeakPtr (const SharedPtr<T>& other)
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_ptr		(other.m_ptr)
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_state	(other.m_state)
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	acquire();
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5686801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
5696801c0680107ff001b065db07b125d622926f311Mika Isojärviinline WeakPtr<T>::~WeakPtr (void)
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	release();
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Assign from another weak pointer.
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param other Weak reference.
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return Reference to this WeakPtr.
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * The current weak reference is removed first and then a new weak reference
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * to the object pointed by other is taken.
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
5826801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
5836801c0680107ff001b065db07b125d622926f311Mika Isojärviinline WeakPtr<T>& WeakPtr<T>::operator= (const WeakPtr<T>& other)
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (this == &other)
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return *this;
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	release();
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_ptr	= other.m_ptr;
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_state	= other.m_state;
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	acquire();
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return *this;
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Assign from shared pointer.
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param other Shared pointer.
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return Reference to this WeakPtr.
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * The current weak reference is removed first and then a new weak reference
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * to the object pointed by other is taken.
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
6066801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
6076801c0680107ff001b065db07b125d622926f311Mika Isojärviinline WeakPtr<T>& WeakPtr<T>::operator= (const SharedPtr<T>& other)
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	release();
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_ptr	= other.m_ptr;
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_state	= other.m_state;
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	acquire();
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return *this;
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6196801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
6206801c0680107ff001b065db07b125d622926f311Mika Isojärviinline void WeakPtr<T>::acquire (void)
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_state)
6236801c0680107ff001b065db07b125d622926f311Mika Isojärvi		deAtomicIncrement32(&m_state->weakRefCount);
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6266801c0680107ff001b065db07b125d622926f311Mika Isojärvitemplate<typename T>
6276801c0680107ff001b065db07b125d622926f311Mika Isojärviinline void WeakPtr<T>::release (void)
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_state)
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6316801c0680107ff001b065db07b125d622926f311Mika Isojärvi		if (deAtomicDecrement32(&m_state->weakRefCount) == 0)
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6336801c0680107ff001b065db07b125d622926f311Mika Isojärvi			delete m_state;
6346801c0680107ff001b065db07b125d622926f311Mika Isojärvi			m_state	= DE_NULL;
6356801c0680107ff001b065db07b125d622926f311Mika Isojärvi			m_ptr	= DE_NULL;
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // de
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif // _DESHAREDPTR_HPP
643