软件架构设计之Utility模块——智能指针

一:前言

         大家应该明白智能指针的用途(管理动态对象的生命期)及好处。其他话就不多说了,直接看如何实现吧。你将会看到一个基于策略而实作出的无比强大,灵活的智能指针。参考的依然是《Modern C++ Design》一书。

二:原理说明

         软件工程比其他工程有更丰富的多样性。你可以采用多种正确的方法去完成一件事情。一旦你选择了一种解决方案,便会有一大堆变化随之涌现,大至系统架构,小至程序片段。设计的多样性不断困扰着程序员。什么是最好的解决方法?是Events,还是Observers?Callbacks?virtuals?Template?任何设计结构上的问题,都有许多合适的解法,然而他们各有不同规格,并且各有优缺点。因此我们会面临各种不同的抉择。在“一个全功能型接口下实作所有东西”来满足我们各种不同的抉择显然会是失败的。

         Policy有助于我们设计出安全,有效率,高度弹性且高复用性的“设计元素”。所谓Policy:定义一个小型Class或Class Template,他们只是单纯的完成某一方面的主题,在“遵循Policy接口”的前提下,你可以采用任何方法来实作Policy。接着你可以混合和匹配各种Policy,就可以完成一个“行为集”。

         接下来采用此原理来实现我们的“智能指针”。实作完后大家可以认真理解Policy-base design(基于策略的设计)

三:实作

         先来划分智能指针的主题(将其划分为5个):1.所管理的对象类型(T)2.拥有权策略(OwnerPolicy)3.安全检查策略(CheckPolicy)4.存储策略(StoragePolicy)5.线程策略(ThreadPolicy)。将每个主题作为HTSmartPtr的模板参数。一个主题仅涉及某一特定功能(他们提供统一的接口)。在遵循相应主题的接口下,你可以用不同的方式(Policy实现)完成该主题所需的功能。在每个主题下,你可以选择一种方式(Policy实现)来完成HTSmartPtr。没选择一种不同的Policy实现,你都会产生一种新的智能指针。因此甚至你可以说,可以产生无穷无尽的智能指针。

         现在的问题我的主题一开始划分不正确怎么办。Policy只是很单纯的完成某一功能,因此你完全可以把原因划在A主题的Policy实现,改换成B主题下。这不需要动大量的代码,因为我们已将HTSmartPtr与Policy实现解耦。HTSmartPtr是由Policy实现组合产生的,只不过将这些Policy实现分类。而与HTSmartPt无关。

1.   拥有权策略(OwnerPolicy)

这里我仅提供拥有权策略的三个Policy实现:引用计数,引用计数的观察者,作用域为范围。

由于引用计数及观察者是配套使用的,因此一起讲:

引用计数:等同于boost中的share_ptr。采用该方案的智能指针是可以共享的。

观察者:等同于boost中的weak_ptr。采用该方案的智能指针是不允许外界访问其拥有的对象,必须转换为引用计数(此过程可以判断该对象是否还有效,有效防止类成员变量为指针类型可能出现的野指针问题)。

作用域为范围:用于局部变量,退出作用域时自动释放。不可共享。

看代码:

class HTCounter // 引用智能指针计数器
{
private:
	HTCounter(HTCounter const & );
	HTCounter& operator = (HTCounter const & );

public:
	HTCounter() : m_nRefCount(0), m_nWeakCount(0) {}

	void RefAdd() {++m_nRefCount;}
	bool RefRelease() {--m_nRefCount; return m_nRefCount == 0;}
	HT_UINT GetRefCount() { return m_nRefCount; }

	void WeakAdd() {++m_nWeakCount;}
	bool WeakRelease() {--m_nWeakCount; return m_nWeakCount == 0;}
	HT_UINT GetWeakCount() { return m_nWeakCount; }

	void Swap(HTCounter& rhs)
	{ std::swap(m_nRefCount, rhs.m_nRefCount); std::swap(m_nWeakCount, rhs.m_nWeakCount);}

private:
	HT_UINT m_nRefCount;	// 实际引用计数值
	HT_UINT m_nWeakCount;	// 观察者的引用计数值
};

template <class P>
class WeakCounted;

template <class P>
class RefCounted // 引用计数
{
	template <typename T> friend class WeakCounted;
public:
	RefCounted() : m_pCount(0) {}
	RefCounted(const RefCounted& rhs) : m_pCount(rhs.m_pCount) {}

	template <typename P1>
	RefCounted(const WeakCounted<P1>& rhs) : m_pCount(reinterpret_cast<const WeakCounted<P1>&>(rhs).ValidCounter()) {}

	template <typename P1>
	RefCounted(const RefCounted<P1>& rhs) : m_pCount(reinterpret_cast<const RefCounted&>(rhs).m_pCount)
	{}

	void NewCount()
	{
		m_pCount = static_cast<HTCounter*>(
			HTMemSmall<>::operator new(sizeof(HTCounter)));
		assert(m_pCount);
		new (m_pCount)HTCounter;
		m_pCount->RefAdd();
	}

	P Clone(const P& val)
	{
		if (m_pCount)
			m_pCount->RefAdd();
		return m_pCount ? val : HT_NULL;
	}

	bool Release(const P&)
	{
		if (m_pCount && m_pCount->RefRelease())
		{
			// 当引用计数、观察者计数均为0时释放计数器
			if (!m_pCount->GetWeakCount())
			{
				m_pCount->~HTCounter();
				HTMemSmall<>::operator delete(m_pCount, sizeof(HTCounter));
				m_pCount = 0;
			}
			return true;
		}

		return false;
	}

	void Swap(RefCounted& rhs)
	{
		std::swap(m_pCount, rhs.m_pCount);
	}

private:
	HTCounter*  m_pCount;
};

template <class P>
class WeakCounted // 观察者计数
{
public:
	WeakCounted() : m_pCount(0) {}
	WeakCounted(const WeakCounted& rhs) : m_pCount(rhs.m_pCount) {}

	template <typename P1>
	WeakCounted(const RefCounted<P1>& rhs) : m_pCount(reinterpret_cast<const RefCounted<P1>&>(rhs).m_pCount) {}
	template <typename P1>
	WeakCounted(const WeakCounted<P1>& rhs) : m_pCount(reinterpret_cast<const WeakCounted&>(rhs).m_pCount) {}

	void NewCount() { assert(false); }

	P Clone(const P& val)
	{
		if (m_pCount)
			m_pCount->WeakAdd();
		return val;
	}

	bool Release(const P&)
	{
		if (m_pCount && m_pCount->WeakRelease())
		{
			// 当引用计数、观察者计数均为0时释放计数器
			if (!m_pCount->GetShareCount())
			{
				HTMemSmall<>::operator delete(m_pCount, sizeof(HTCounter));
				m_pCount = 0;
			}
		}

		return false;
	}

	HTCounter* ValidCounter() const
	{
		// 当引用计数非0
		if (m_pCount && m_pCount->GetShareCount())
			return m_pCount;

		return HT_NULL;
	}

	void Swap(WeakCounted& rhs)
	{ std::swap(m_pCount, rhs.m_pCount); }

	template <typename T> friend class RefCounted;
private:
	HTCounter* m_pCount;
};

template <class P>
class OwnerScoped
{
public:
	void NewCount() {}
	bool Release(const P&) { return true; }
};

2.   安全检查策略(CheckPolicy)

这里仅提供两种Plicy实现:CheckNo(不进行任何检查),CheckAssert(提领前进行assert检查是否为null)。

CheckNo: 不提供任何检验

CheckAssert:// 提领前断言检验

template <class P>
struct CheckNo
{
	CheckNo() {}
	template <class P1>
	CheckNo(const CheckNo<P1>&) {}
	static void OnDefault(const P&) {}
	static void OnInit(const P&) {}
	static void OnDereference(const P&) {}
	static void Swap(CheckNo&) {}
};

template <class P>
struct CheckAssert
{
	CheckAssert() {}

	template <class P1>
	CheckAssert(const CheckAssert<P1>&) {}
	template <class P1>
	CheckAssert(const CheckNo<P1>&) {}

	static void OnDefault(const P&) {}
	static void OnInit(const P&) {}
	static void OnDereference(P val)
	{
		assert(val);
		(void) val;
	}

	static void Swap(CheckAssert&) {}
};

3.   存储策略(StoragePolicy):

这里仅提供三种Policy实现:StorageNo(不为所管理的对象分配内存),StoragePool(在内存池中分配对象),StorageNew(即使用new 分配对象,delete释放对象)。

StorageNo:不含分配对象内存功能

StoragePool:在内存池中为对象分配空间,这里选用的是HTMemFlex,可参看内存分配部分

StorageNew:使用new分配,delete释放

template <typename T>
class HTStorageNo
{
public:
	typedef T			value_type;
	typedef T*			pointer;
	typedef const T*	const_pointer;
	typedef T&			reference;
	typedef const T&	const_reference;
	typedef T*			stored_type;

	HTStorageNo() : m_pT(0) {}
	HTStorageNo(const HTStorageNo&) {}
	template <class U>
	HTStorageNo(const HTStorageNo<U>&);// {}
// 	template <class U>
// 	HTStorageNo(const YKStorageChunk<U>&) {}

	void Create() { assert(false); }
	void  Destroy() { assert(false); }

	pointer operator-> () const { BOOST_STATIC_ASSERT(0); return m_pT;}
	reference operator* () const { BOOST_STATIC_ASSERT(0); return *m_pT;}
	void Swap(HTStorageNo& rhs)
	{ std::swap(m_pT, rhs.m_pT); }

	friend inline pointer GetImpl(const HTStorageNo& sp)
	{ return sp.m_pT; }
	friend inline const stored_type& GetImplRef(const HTStorageNo& sp)
	{ return sp.m_pT; }
	friend inline stored_type& GetImplRef(HTStorageNo& sp)
	{ return sp.m_pT; }

private:
	stored_type		m_pT;
};

template <typename T>
class HTStorageNew
{
public:
	typedef T			value_type;
	typedef T*			pointer;
	typedef const T*	const_pointer;
	typedef T&			reference;
	typedef const T&	const_reference;
	typedef T*			stored_type;

	void Create() { m_pT = new T(); }
	void  Destroy() { delete m_pT; m_pT = 0; }

	pointer operator-> () const {return m_pT;}
	reference operator* () const {return *m_pT;}
	void Swap(HTStorageNew& rhs)
	{std::swap(m_pT, rhs.m_pT);}

	friend inline pointer GetImpl(const HTStorageNew& sp)
	{return sp.m_pT;}
	friend inline const stored_type& GetImplRef(const HTStorageNew& sp)
	{return sp.m_pT;}
	friend inline stored_type& GetImplRef(HTStorageNew& sp)
	{return sp.m_pT;}

private:
	stored_type		m_pT;
};

template <typename T>
class HTStoragePool : public HTMemFlex<T>
{
public:
	typedef T			value_type;
	typedef T*			pointer;
	typedef const T*	const_pointer;
	typedef T&			reference;
	typedef const T&	const_reference;
	typedef T*			stored_type;

public:
	HTStoragePool() : m_pT(0) {}
	HTStoragePool(const HTStoragePool&) {}
	template <class U>
	HTStoragePool(const HTStoragePool<U>&) {}
// 	template <class U>
// 	HTStoragePool(const YKStorageNo<U>&) {}

	HTStoragePool(const stored_type& p) : m_pT(p) {}
	~HTStoragePool() {}

	void Create() { m_pT = Allocate(sizeof(value_type)); }
	void  Destroy() { Deallocate(m_pT); m_pT = 0; }

	pointer operator-> () const {return m_pT;}
	reference operator* () const {return *m_pT;}
	void Swap(HTStoragePool& rhs)
	{std::swap(m_pT, rhs.m_pT);}

	friend inline pointer GetImpl(const HTStoragePool& sp)
	{return sp.m_pT;}
	friend inline const stored_type& GetImplRef(const HTStoragePool& sp)
	{return sp.m_pT;}
	friend inline stored_type& GetImplRef(HTStoragePool& sp)
	{return sp.m_pT;}

private:
	stored_type		m_pT;
};

4.   线程策略(ThreadPolicy)

         两个Policy实现:ThreadSingle(单线程实现),ThreadMulti(多线程实现)

         ThreadSingle:不用加锁保护,用于单线程环境。

         ThreadMulti:可用于多线程环境。

暂不实现该策略,等实现完线程部分再来实在该策略。

5.   将一切组装起来

默认实现一个引用计数,不进行任何检查,使用自定义内存池来分配对象的智能指针。
template <typename T, 
	template <class> class OwnerPolicy = RefCounted,
	template <class> class CheckPolicy = CheckNo,
	template <class> class StoragePolicy = HTStoragePool>
class HTSmartPtr : public StoragePolicy<T>
	, public OwnerPolicy<typename StoragePolicy<T>::pointer>
	, public CheckPolicy<typename StoragePolicy<T>::stored_type>
{
	typedef StoragePolicy<T>		MP;
	typedef OwnerPolicy<typename StoragePolicy<T>::pointer> OP;
	typedef CheckPolicy<typename StoragePolicy<T>::stored_type> KP;
public:
	typedef typename MP::reference			reference;
	typedef typename MP::const_reference	const_reference;
	typedef typename MP::pointer			pointer;
	typedef typename MP::const_pointer		const_pointer;
	typedef typename MP::value_type			value_type;

public:
	HTSmartPtr(bool bNew = false)	// 需要分配对象则传true
	{
		if (bNew)
		{
			NewObj();
		}
	}

	void NewObj()
	{
		assert(!ValidObj());
		Create();
		NewCount();
	}

	HTSmartPtr(int rhs)	// 只接受HT_NULL,不接受裸指针
	{
		assert(rhs == HT_NULL);
		HTSmartPtr temp;
		temp.Swap(*this);
	}

	HTSmartPtr(HTSmartPtr& rhs)
		: MP(rhs), OP(rhs), KP(rhs)
	{
		GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
	}

	template <typename T1, 
		template <class> class OP1,
		template <class> class KP1,
		template <class> class MP1>
	HTSmartPtr(const HTSmartPtr<T1, OP1, KP1, MP1>& rhs)
		: MP(rhs), OP(rhs), KP(rhs)
	{
		GetImplRef(*this) = OP::Clone(HT_Safe_DownCast<pointer>(GetImplRef(rhs)));
	}

	template <typename T1, 
		template <class> class OP1,
		template <class> class KP1,
		template <class> class MP1>
	HTSmartPtr(HTSmartPtr<T1, OP1, KP1, MP1>& rhs)
		: MP(rhs), OP(rhs), KP(rhs)
	{
		GetImplRef(*this) = OP::Clone(HT_Safe_DownCast<pointer>(GetImplRef(rhs)));
	}

	HTSmartPtr& operator= (HTSmartPtr& rhs)
	{
		HTSmartPtr temp(rhs);
		temp.Swap(*this);
		return *this;
	}

	HTSmartPtr& operator= (int rhs)
	{
		assert(rhs == HT_NULL);
		HTSmartPtr temp;
		temp.Swap(*this);
		return *this;
	}

	template <typename T1, 
		template <class> class OP1,
		template <class> class KP1,
		template <class> class MP1>
	HTSmartPtr& operator= (const HTSmartPtr<T1, OP1, KP1, MP1>& rhs)
	{
		HTSmartPtr temp(rhs);
		temp.Swap(*this);
		return *this;
	}

	template <typename T1, 
		template <class> class OP1,
		template <class> class KP1,
		template <class> class MP1>
	HTSmartPtr& operator= (HTSmartPtr<T1, OP1, KP1, MP1>& rhs)
	{
		HTSmartPtr temp(rhs);
		temp.Swap(*this);
		return *this;
	}

	void Swap(HTSmartPtr& rhs)
	{
		OP::Swap(rhs);
		KP::Swap(rhs);
		MP::Swap(rhs);
	}

	~HTSmartPtr() 
	{
		if (OP::Release(GetImpl(*static_cast<MP*>(this))))
		{
			Destroy();
		}
	}

	pointer operator-> ()
	{
		KP::OnDereference(GetImplRef(*this));
		return MP::operator ->();
	}

	pointer operator-> () const
	{
		KP::OnDereference(GetImplRef(*this));
		return MP::operator ->();
	}

	reference operator* ()
	{
		KP::OnDereference(GetImplRef(*this));
		return MP::operator *();
	}

	reference operator* () const
	{
		KP::OnDereference(GetImplRef(*this));
		return MP::operator *();
	}

	inline friend HT_BOOL operator==(const HTSmartPtr& lhs, const_pointer rhs)
	{ return GetImpl(lhs) == rhs; }

	inline friend HT_BOOL operator==(const_pointer lhs, const HTSmartPtr& rhs)
	{ return rhs == lhs; }

	inline friend HT_BOOL operator!=(const HTSmartPtr& lhs, const_pointer rhs)
	{ return !(lhs == rhs); }

	inline friend HT_BOOL operator!=(const_pointer lhs, const HTSmartPtr& rhs)
	{ return rhs != lhs; }

	template <typename T1, 
		template <class> class OP1,
		template <class> class KP1,
		template <class> class MP1>
	inline HT_BOOL operator== (const HTSmartPtr<T1, OP1, KP1, MP1>& rhs) const
	{return *this == GetImpl(rhs);}

	template <typename T1, 
		template <class> class OP1,
		template <class> class KP1,
		template <class> class MP1>
	inline bool operator!= (const HTSmartPtr<T1, OP1, KP1, MP1>& rhs) const
	{return !(*this == rhs);}

	template <typename T1, 
		template <class> class OP1,
		template <class> class KP1,
		template <class> class MP1>
	inline bool operator< (const HTSmartPtr<T1, OP1, KP1, MP1>& rhs) const
	{return !(*this < rhs);}

	template <typename T1, 
		template <class> class OP1,
		template <class> class KP1,
		template <class> class MP1>
	inline bool operator> (const HTSmartPtr<T1, OP1, KP1, MP1>& rhs) const
	{return !(*this > rhs);}

	inline pointer GetValue()
	{ return GetImpl(*this); }
	inline pointer GetValue() const
	{ return GetImpl(*this); }

	inline bool ValidObj()
	{ return GetImpl(*this) != 0; }
	inline bool ValidObj() const
	{ return GetImpl(*this) != 0; }


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值