mirror of
				https://github.com/pocoproject/poco.git
				synced 2025-11-03 19:40:37 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			438 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			438 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//
 | 
						|
// SharedPtr.h
 | 
						|
//
 | 
						|
// $Id: //poco/1.4/Foundation/include/Poco/SharedPtr.h#1 $
 | 
						|
//
 | 
						|
// Library: Foundation
 | 
						|
// Package: Core
 | 
						|
// Module:  SharedPtr
 | 
						|
//
 | 
						|
// Definition of the SharedPtr template class.
 | 
						|
//
 | 
						|
// Copyright (c) 2005-2008, Applied Informatics Software Engineering GmbH.
 | 
						|
// and Contributors.
 | 
						|
//
 | 
						|
// Permission is hereby granted, free of charge, to any person or organization
 | 
						|
// obtaining a copy of the software and accompanying documentation covered by
 | 
						|
// this license (the "Software") to use, reproduce, display, distribute,
 | 
						|
// execute, and transmit the Software, and to prepare derivative works of the
 | 
						|
// Software, and to permit third-parties to whom the Software is furnished to
 | 
						|
// do so, all subject to the following:
 | 
						|
// 
 | 
						|
// The copyright notices in the Software and this entire statement, including
 | 
						|
// the above license grant, this restriction and the following disclaimer,
 | 
						|
// must be included in all copies of the Software, in whole or in part, and
 | 
						|
// all derivative works of the Software, unless such copies or derivative
 | 
						|
// works are solely in the form of machine-executable object code generated by
 | 
						|
// a source language processor.
 | 
						|
// 
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 | 
						|
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 | 
						|
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 | 
						|
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | 
						|
// DEALINGS IN THE SOFTWARE.
 | 
						|
//
 | 
						|
 | 
						|
 | 
						|
#ifndef Foundation_SharedPtr_INCLUDED
 | 
						|
#define Foundation_SharedPtr_INCLUDED
 | 
						|
 | 
						|
 | 
						|
#include "Poco/Foundation.h"
 | 
						|
#include "Poco/Exception.h"
 | 
						|
#include "Poco/AtomicCounter.h"
 | 
						|
#include <algorithm>
 | 
						|
 | 
						|
 | 
						|
namespace Poco {
 | 
						|
 | 
						|
 | 
						|
class ReferenceCounter
 | 
						|
	/// Simple ReferenceCounter object, does not delete itself when count reaches 0.
 | 
						|
{
 | 
						|
public:
 | 
						|
	ReferenceCounter(): _cnt(1)
 | 
						|
	{
 | 
						|
	}
 | 
						|
 | 
						|
	void duplicate()
 | 
						|
	{
 | 
						|
		++_cnt;
 | 
						|
	}
 | 
						|
 | 
						|
	int release()
 | 
						|
	{
 | 
						|
		return --_cnt;
 | 
						|
	}
 | 
						|
	
 | 
						|
	int referenceCount() const
 | 
						|
	{
 | 
						|
		return _cnt.value();
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	AtomicCounter _cnt;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
template <class C>
 | 
						|
class ReleasePolicy
 | 
						|
	/// The default release policy for SharedPtr, which
 | 
						|
	/// simply uses the delete operator to delete an object.
 | 
						|
{
 | 
						|
public:
 | 
						|
	static void release(C* pObj)
 | 
						|
		/// Delete the object.
 | 
						|
		/// Note that pObj can be 0.
 | 
						|
	{
 | 
						|
		delete pObj;
 | 
						|
	}
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
template <class C>
 | 
						|
class ReleaseArrayPolicy
 | 
						|
	/// The release policy for SharedPtr holding arrays.
 | 
						|
{
 | 
						|
public:
 | 
						|
	static void release(C* pObj)
 | 
						|
		/// Delete the object.
 | 
						|
		/// Note that pObj can be 0.
 | 
						|
	{
 | 
						|
		delete [] pObj;
 | 
						|
	}
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
template <class C, class RC = ReferenceCounter, class RP = ReleasePolicy<C> >
 | 
						|
class SharedPtr
 | 
						|
	/// SharedPtr is a "smart" pointer for classes implementing
 | 
						|
	/// reference counting based garbage collection.
 | 
						|
	/// SharedPtr is thus similar to AutoPtr. Unlike the
 | 
						|
	/// AutoPtr template, which can only be used with
 | 
						|
	/// classes that support reference counting, SharedPtr
 | 
						|
	/// can be used with any class. For this to work, a
 | 
						|
	/// SharedPtr manages a reference count for the object
 | 
						|
	/// it manages.
 | 
						|
	/// 
 | 
						|
	/// SharedPtr works in the following way:
 | 
						|
	/// If an SharedPtr is assigned an ordinary pointer to
 | 
						|
	/// an object (via the constructor or the assignment operator),
 | 
						|
	/// it takes ownership of the object and the object's reference 
 | 
						|
	/// count is initialized to one.
 | 
						|
	/// If the SharedPtr is assigned another SharedPtr, the
 | 
						|
	/// object's reference count is incremented by one.
 | 
						|
	/// The destructor of SharedPtr decrements the object's
 | 
						|
	/// reference count by one and deletes the object if the
 | 
						|
	/// reference count reaches zero.
 | 
						|
	/// SharedPtr supports dereferencing with both the ->
 | 
						|
	/// and the * operator. An attempt to dereference a null
 | 
						|
	/// SharedPtr results in a NullPointerException being thrown.
 | 
						|
	/// SharedPtr also implements all relational operators and
 | 
						|
	/// a cast operator in case dynamic casting of the encapsulated data types
 | 
						|
	/// is required.
 | 
						|
{
 | 
						|
public:
 | 
						|
	SharedPtr(): _pCounter(new RC), _ptr(0)
 | 
						|
	{
 | 
						|
	}
 | 
						|
 | 
						|
	SharedPtr(C* ptr): _pCounter(new RC), _ptr(ptr)
 | 
						|
	{
 | 
						|
	}
 | 
						|
 | 
						|
	template <class Other, class OtherRP> 
 | 
						|
	SharedPtr(const SharedPtr<Other, RC, OtherRP>& ptr): _pCounter(ptr._pCounter), _ptr(const_cast<Other*>(ptr.get()))
 | 
						|
	{
 | 
						|
		_pCounter->duplicate();
 | 
						|
	}
 | 
						|
 | 
						|
	SharedPtr(const SharedPtr& ptr): _pCounter(ptr._pCounter), _ptr(ptr._ptr)
 | 
						|
	{
 | 
						|
		_pCounter->duplicate();
 | 
						|
	}
 | 
						|
 | 
						|
	~SharedPtr()
 | 
						|
	{
 | 
						|
		release();
 | 
						|
	}
 | 
						|
 | 
						|
	SharedPtr& assign(C* ptr)
 | 
						|
	{
 | 
						|
		if (get() != ptr)
 | 
						|
		{
 | 
						|
			RC* pTmp = new RC;
 | 
						|
			release();
 | 
						|
			_pCounter = pTmp;
 | 
						|
			_ptr = ptr;
 | 
						|
		}
 | 
						|
		return *this;
 | 
						|
	}
 | 
						|
	
 | 
						|
	SharedPtr& assign(const SharedPtr& ptr)
 | 
						|
	{
 | 
						|
		if (&ptr != this)
 | 
						|
		{
 | 
						|
			SharedPtr tmp(ptr);
 | 
						|
			swap(tmp);
 | 
						|
		}
 | 
						|
		return *this;
 | 
						|
	}
 | 
						|
	
 | 
						|
	template <class Other, class OtherRP>
 | 
						|
	SharedPtr& assign(const SharedPtr<Other, RC, OtherRP>& ptr)
 | 
						|
	{
 | 
						|
		if (ptr.get() != _ptr)
 | 
						|
		{
 | 
						|
			SharedPtr tmp(ptr);
 | 
						|
			swap(tmp);
 | 
						|
		}
 | 
						|
		return *this;
 | 
						|
	}
 | 
						|
 | 
						|
	SharedPtr& operator = (C* ptr)
 | 
						|
	{
 | 
						|
		return assign(ptr);
 | 
						|
	}
 | 
						|
 | 
						|
	SharedPtr& operator = (const SharedPtr& ptr)
 | 
						|
	{
 | 
						|
		return assign(ptr);
 | 
						|
	}
 | 
						|
 | 
						|
	template <class Other, class OtherRP>
 | 
						|
	SharedPtr& operator = (const SharedPtr<Other, RC, OtherRP>& ptr)
 | 
						|
	{
 | 
						|
		return assign<Other>(ptr);
 | 
						|
	}
 | 
						|
 | 
						|
	void swap(SharedPtr& ptr)
 | 
						|
	{
 | 
						|
		std::swap(_ptr, ptr._ptr);
 | 
						|
		std::swap(_pCounter, ptr._pCounter);
 | 
						|
	}
 | 
						|
 | 
						|
	template <class Other> 
 | 
						|
	SharedPtr<Other, RC, RP> cast() const
 | 
						|
		/// Casts the SharedPtr via a dynamic cast to the given type.
 | 
						|
		/// Returns an SharedPtr containing NULL if the cast fails.
 | 
						|
		/// Example: (assume class Sub: public Super)
 | 
						|
		///    SharedPtr<Super> super(new Sub());
 | 
						|
		///    SharedPtr<Sub> sub = super.cast<Sub>();
 | 
						|
		///    poco_assert (sub.get());
 | 
						|
	{
 | 
						|
		Other* pOther = dynamic_cast<Other*>(_ptr);
 | 
						|
		if (pOther)
 | 
						|
			return SharedPtr<Other, RC, RP>(_pCounter, pOther);
 | 
						|
		return SharedPtr<Other, RC, RP>();
 | 
						|
	}
 | 
						|
 | 
						|
	template <class Other> 
 | 
						|
	SharedPtr<Other, RC, RP> unsafeCast() const
 | 
						|
		/// Casts the SharedPtr via a static cast to the given type.
 | 
						|
		/// Example: (assume class Sub: public Super)
 | 
						|
		///    SharedPtr<Super> super(new Sub());
 | 
						|
		///    SharedPtr<Sub> sub = super.unsafeCast<Sub>();
 | 
						|
		///    poco_assert (sub.get());
 | 
						|
	{
 | 
						|
		Other* pOther = static_cast<Other*>(_ptr);
 | 
						|
		return SharedPtr<Other, RC, RP>(_pCounter, pOther);
 | 
						|
	}
 | 
						|
 | 
						|
	C* operator -> ()
 | 
						|
	{
 | 
						|
		return deref();
 | 
						|
	}
 | 
						|
 | 
						|
	const C* operator -> () const
 | 
						|
	{
 | 
						|
		return deref();
 | 
						|
	}
 | 
						|
 | 
						|
	C& operator * ()
 | 
						|
	{
 | 
						|
		return *deref();
 | 
						|
	}
 | 
						|
 | 
						|
	const C& operator * () const
 | 
						|
	{
 | 
						|
		return *deref();
 | 
						|
	}
 | 
						|
 | 
						|
	C* get()
 | 
						|
	{
 | 
						|
		return _ptr;
 | 
						|
	}
 | 
						|
 | 
						|
	const C* get() const
 | 
						|
	{
 | 
						|
		return _ptr;
 | 
						|
	}
 | 
						|
 | 
						|
	operator C* ()
 | 
						|
	{
 | 
						|
		return _ptr;
 | 
						|
	}
 | 
						|
	
 | 
						|
	operator const C* () const
 | 
						|
	{
 | 
						|
		return _ptr;
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator ! () const
 | 
						|
	{
 | 
						|
		return _ptr == 0;
 | 
						|
	}
 | 
						|
 | 
						|
	bool isNull() const
 | 
						|
	{
 | 
						|
		return _ptr == 0;
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator == (const SharedPtr& ptr) const
 | 
						|
	{
 | 
						|
		return get() == ptr.get();
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator == (const C* ptr) const
 | 
						|
	{
 | 
						|
		return get() == ptr;
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator == (C* ptr) const
 | 
						|
	{
 | 
						|
		return get() == ptr;
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator != (const SharedPtr& ptr) const
 | 
						|
	{
 | 
						|
		return get() != ptr.get();
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator != (const C* ptr) const
 | 
						|
	{
 | 
						|
		return get() != ptr;
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator != (C* ptr) const
 | 
						|
	{
 | 
						|
		return get() != ptr;
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator < (const SharedPtr& ptr) const
 | 
						|
	{
 | 
						|
		return get() < ptr.get();
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator < (const C* ptr) const
 | 
						|
	{
 | 
						|
		return get() < ptr;
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator < (C* ptr) const
 | 
						|
	{
 | 
						|
		return get() < ptr;
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator <= (const SharedPtr& ptr) const
 | 
						|
	{
 | 
						|
		return get() <= ptr.get();
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator <= (const C* ptr) const
 | 
						|
	{
 | 
						|
		return get() <= ptr;
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator <= (C* ptr) const
 | 
						|
	{
 | 
						|
		return get() <= ptr;
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator > (const SharedPtr& ptr) const
 | 
						|
	{
 | 
						|
		return get() > ptr.get();
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator > (const C* ptr) const
 | 
						|
	{
 | 
						|
		return get() > ptr;
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator > (C* ptr) const
 | 
						|
	{
 | 
						|
		return get() > ptr;
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator >= (const SharedPtr& ptr) const
 | 
						|
	{
 | 
						|
		return get() >= ptr.get();
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator >= (const C* ptr) const
 | 
						|
	{
 | 
						|
		return get() >= ptr;
 | 
						|
	}
 | 
						|
 | 
						|
	bool operator >= (C* ptr) const
 | 
						|
	{
 | 
						|
		return get() >= ptr;
 | 
						|
	}
 | 
						|
	
 | 
						|
	int referenceCount() const
 | 
						|
	{
 | 
						|
		return _pCounter->referenceCount();
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	C* deref() const
 | 
						|
	{
 | 
						|
		if (!_ptr)
 | 
						|
			throw NullPointerException();
 | 
						|
 | 
						|
		return _ptr;
 | 
						|
	}
 | 
						|
 | 
						|
	void release()
 | 
						|
	{
 | 
						|
		poco_assert_dbg (_pCounter);
 | 
						|
		int i = _pCounter->release();
 | 
						|
		if (i == 0)
 | 
						|
		{
 | 
						|
			RP::release(_ptr);
 | 
						|
			_ptr = 0;
 | 
						|
 | 
						|
			delete _pCounter;
 | 
						|
			_pCounter = 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	SharedPtr(RC* pCounter, C* ptr): _pCounter(pCounter), _ptr(ptr)
 | 
						|
		/// for cast operation
 | 
						|
	{
 | 
						|
		poco_assert_dbg (_pCounter);
 | 
						|
		_pCounter->duplicate();
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	RC* _pCounter;
 | 
						|
	C*  _ptr;
 | 
						|
 | 
						|
	template <class OtherC, class OtherRC, class OtherRP> friend class SharedPtr;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
template <class C, class RC, class RP>
 | 
						|
inline void swap(SharedPtr<C, RC, RP>& p1, SharedPtr<C, RC, RP>& p2)
 | 
						|
{
 | 
						|
	p1.swap(p2);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
} // namespace Poco
 | 
						|
 | 
						|
 | 
						|
#endif // Foundation_SharedPtr_INCLUDED
 |