Posted on 2008-11-13 17:37
空心菜 阅读(2502)
评论(3) 编辑 收藏 引用
看一下Ogre里面的ShagedPtr,其实就是一个Smart Pointers。下面的代码是删去了原有注释的。现不谈里面的MUTEX。
#ifndef __SharedPtr_H__
#define __SharedPtr_H__
#include "OgrePrerequisites.h"
namespace Ogre {
template<class T> class SharedPtr {
protected:
T* pRep;
unsigned int* pUseCount; //看到这里,应该能知道,SharedPtr是通过引用计数来管理pRep的寿命
public:
OGRE_AUTO_SHARED_MUTEX
SharedPtr() : pRep(0), pUseCount(0)
{
OGRE_SET_AUTO_SHARED_MUTEX_NULL
}//允许有一个空的SharedPtr,不指向任何的对象。
template< class Y>
explicit SharedPtr(Y* rep) : pRep(rep), pUseCount(new unsigned int(1))
{
OGRE_SET_AUTO_SHARED_MUTEX_NULL
OGRE_NEW_AUTO_SHARED_MUTEX
}//这个写法是Member Templates,很有用,这样就允许用一个Y对象的指针来初始化一个SharedPtr<T>
//下面还能看到很多这样的Member Templates
//要是以前没见过的人,推荐看一下C++ Templates的第5章、第3节
//try this: vector<int> intvec;
// vector<float> floatvec;
// floatvec = intvec ???????
//提一下,所有的初始化函数都没有检查rep是否非空,所以SharedPtr接受一个Null指针
//安全检查在每次调用的时候
//这里还使用了关键字explicit,禁止了隐式转换
SharedPtr(const SharedPtr& r)
: pRep(0), pUseCount(0)
{
OGRE_SET_AUTO_SHARED_MUTEX_NULL
OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
{
OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
pRep = r.pRep; //注意下与后面的不同
pUseCount = r.pUseCount;
// Handle zero pointer gracefully to manage STL containers
if(pUseCount)
{
++(*pUseCount);
}
}
}
SharedPtr& operator=(const SharedPtr& r) {
if (pRep == r.pRep)
return *this;
SharedPtr<T> tmp(r);
swap(tmp);
return *this;
}//这里的写法有点意思,本来在pRep指向r.pRep之前对pRep做一次release,
//但是这里没看到,其实是通过tmp这个局部变量的自动解析实现的。
template< class Y>
SharedPtr(const SharedPtr<Y>& r)
: pRep(0), pUseCount(0)
{
OGRE_SET_AUTO_SHARED_MUTEX_NULL
OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
{
OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
pRep = r.getPointer(); //这里用的是函数,和上面那个的区别??
pUseCount = r.useCountPointer();
// Handle zero pointer gracefully to manage STL containers
if(pUseCount)
{
++(*pUseCount);
}
}
}
template< class Y>
SharedPtr& operator=(const SharedPtr<Y>& r) {
if (pRep == r.pRep)
return *this;
SharedPtr<T> tmp(r);
swap(tmp);
return *this;
}
virtual ~SharedPtr() {
release();
}
inline T& operator*() const { assert(pRep); return *pRep; }
inline T* operator->() const { assert(pRep); return pRep; }
//在用的时候检查pRep的合法性
inline T* get() const { return pRep; }
void bind(T* rep) {
assert(!pRep && !pUseCount);
OGRE_NEW_AUTO_SHARED_MUTEX
OGRE_LOCK_AUTO_SHARED_MUTEX
pUseCount = new unsigned int(1);
pRep = rep;
}
inline bool unique() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount == 1; }
inline unsigned int useCount() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount; }
inline unsigned int* useCountPointer() const { return pUseCount; }
inline T* getPointer() const { return pRep; }
inline bool isNull(void) const { return pRep == 0; }
inline void setNull(void) {
if (pRep)
{
// can't scope lock mutex before release incase deleted
release();
pRep = 0;
pUseCount = 0;
}
}
protected:
inline void release(void)
{
bool destroyThis = false;
OGRE_MUTEX_CONDITIONAL(OGRE_AUTO_MUTEX_NAME)
{
OGRE_LOCK_AUTO_SHARED_MUTEX
if (pUseCount)
{
if (--(*pUseCount) == 0)
{
destroyThis = true;
}
}
}
if (destroyThis)
destroy();
OGRE_SET_AUTO_SHARED_MUTEX_NULL
}
virtual void destroy(void)
{
delete pRep;
delete pUseCount;
OGRE_DELETE_AUTO_SHARED_MUTEX
}
virtual void swap(SharedPtr<T> &other)
{
std::swap(pRep, other.pRep);
std::swap(pUseCount, other.pUseCount);
#if OGRE_THREAD_SUPPORT
std::swap(OGRE_AUTO_MUTEX_NAME, other.OGRE_AUTO_MUTEX_NAME);
#endif
}
};
template<class T, class U> inline bool operator==(SharedPtr<T> const& a, SharedPtr<U> const& b)
{
return a.get() == b.get();
}
template<class T, class U> inline bool operator!=(SharedPtr<T> const& a, SharedPtr<U> const& b)
{
return a.get() != b.get();
}
}
#endif
最后有注意到:
inline T* get() const { return pRep; }
inline T* getPointer() const { return pRep; }
不知道为啥要这样,有一个不就行了么。
更多的细节、使用方法放到下次把。