您的位置:首页 > 运维架构 > 网站架构

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

2013-03-18 23:01 211 查看

一:前言

大家应该明白智能指针的用途(管理动态对象的生命期)及好处。其他话就不多说了,直接看如何实现吧。你将会看到一个基于策略而实作出的无比强大,灵活的智能指针。参考的依然是《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; }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: