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

来源:互联网 发布:coc部落城堡升级数据 编辑:程序博客网 时间:2024/05/16 07:56

一:前言

         大家应该明白智能指针的用途(管理动态对象的生命期)及好处。其他话就不多说了,直接看如何实现吧。你将会看到一个基于策略而实作出的无比强大,灵活的智能指针。参考的依然是《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{// 当引用计数非0if (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 Tvalue_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_typem_pT;};template <typename T>class HTStorageNew{public:typedef Tvalue_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_typem_pT;};template <typename T>class HTStoragePool : public HTMemFlex<T>{public:typedef Tvalue_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_typem_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::referencereference;typedef typename MP::const_referenceconst_reference;typedef typename MP::pointerpointer;typedef typename MP::const_pointerconst_pointer;typedef typename MP::value_typevalue_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; }


原创粉丝点击