首页 技术 正文
技术 2022年11月14日
0 收藏 509 点赞 3,333 浏览 4151 个字

基于Handle的资源管理方案,第一时间想到的应该是Windows了,但是真正想让我实施这个方案的,是《游戏编程精粹1》里面的游戏资源管理篇章的给出的方案。在《游戏编程精粹1》里面的资源标示Handle类,是一个极为简单的32位int类型,分为前16位的index和后16位的magic num,magic num主要是用来用作资源的校验的,在获取实例资源和删除实例资源的时候,都会校验一次。这两个数据合成一个int32用来标示唯一的资源。

union
{
enum
{
MAX_BITS_INDEX = ,
MAX_BITS_MAGIC = , MAX_INDEX = ( << MAX_BITS_INDEX) - ,
MAX_MAGIC = ( << MAX_BITS_MAGIC) - ,
}; struct
{
unsigned mIndex : MAX_BITS_INDEX;
unsigned mMagic : MAX_BITS_MAGIC;
}; uint mHandle;
};

当然,这个Handle在书里面是定义成模板了,主要还是转为C++的习惯,变成一种强类型的标示吧,不同资源类型不能相互赋值和转化。

接来下是定义HandleManager,这个类也是一个模板,就跟名字一样,是用来管理Handle的,里面有两个vector,一个是保存正在使用的资源的vector,一个是删除资源后放入的free vector,当用户需要新建一个Handle的时候,会优先从free vector里面查找空的Handle,重新指向新的资源。

但是这个Handle的指向资源实例数组的index是不会变的,会变的只是magic num。总的来说,Handle还是变了。

template<typename DATA, typename RESHANDLE>
DATA * ResHandleMgr<DATA, RESHANDLE>::acquire(RESHANDLE &handle)
{
uint index;
if (mFreeSlots.empty())
{
index = mMagicNums.size();
handle.init(index);
DATA *pData = new DATA();
mUserVec.push_back(pData);
mMagicNums.push_back(handle.getMagic());
}
else
{
index = mFreeSlots.back();
     // init后,magic num 会加一
handle.init(index);
mFreeSlots.pop_back();
mMagicNums[index] = handle.getMagic();
} //return (mUserVec.begin() + index);
UserVec::iterator iter = mUserVec.begin() + index;
return *iter;
}

这个大体就是《游戏编程精粹1》里面的引擎资源管理方案了,要保存资源很简单,持有Handle就行了,要获取和删除资源直接用Handle就行了。但是,估计大家也看来出什么问题了,资源没有自动释放的机制!!!!!!!

于是,我在Handle类里面加了个变量,用来作为引用计数,这里暂时没有引入智能指针(这个引用计数优化的方法应该可以加入一个内存池)

private:
union
{
enum
{
MAX_BITS_INDEX = ,
MAX_BITS_MAGIC = , MAX_INDEX = ( << MAX_BITS_INDEX) - ,
MAX_MAGIC = ( << MAX_BITS_MAGIC) - ,
}; struct
{
unsigned mIndex : MAX_BITS_INDEX;
unsigned mMagic : MAX_BITS_MAGIC;
}; uint mHandle;
};
//保存引用计数
uint *mpRefCount;

在Handle释放的时候,handle.release(),在Handle赋值的时候,handle.addRef,当(*mpRefCount) == 0的时候,就可以释放资源资源了。

一开始的时候,将引用计数设置为static std::map<int, int>(前面一个int表示Handle,后面一个表示引用次数),后来发现效率实在太低,于是改为 uint *mpRefCount指针这种形式,帧数上升了20 FPS左右。。。

这个Handle类大体长这个样子的,基本也可以实现资源的自动释放机制了

template<typename ResType>
class ENGINE_DLL ResHandle
{
public:
ResHandle();
ResHandle(const ResHandle &handle); ~ResHandle(); void init(uint index);
uint getIndex() const;
uint getMagic() const;
uint getHandle() const; bool isNull() const; operator uint() const; void addRef(); void release(); ResHandle &operator =(ResHandle handle)
{
mHandle = handle.getHandle();
if (handle.isNull() == false)
{
assert(handle.mpRefCount != );
if (isNull() == false && mpRefCount)
{
release();
if (mpRefCount != )
assert(mpRefCount == handle.mpRefCount);
}
}
mpRefCount = handle.mpRefCount;
addRef();
return *this;
}private:
union
{
enum
{
MAX_BITS_INDEX = ,
MAX_BITS_MAGIC = , MAX_INDEX = ( << MAX_BITS_INDEX) - ,
MAX_MAGIC = ( << MAX_BITS_MAGIC) - ,
}; struct
{
unsigned mIndex : MAX_BITS_INDEX;
unsigned mMagic : MAX_BITS_MAGIC;
}; uint mHandle;
}; uint *mpRefCount;
};template<typename ResType>
ResHandle<ResType>::ResHandle(const ResHandle &handle) :
mpRefCount()
{
mHandle = handle.getHandle();
mpRefCount = handle.mpRefCount;
addRef();
}template<typename ResType>
ResHandle<ResType>::~ResHandle()
{
release();
}template<typename ResType>
void ResHandle<ResType>::release()
{
if (mHandle != )
{
--(*mpRefCount);
if (*mpRefCount == )
{
//std::cout << "need delete !!!!" << std::endl;
//delete operator
//后面加入
Log::getInstancePtr()->logMsg("release res handle = %d", mHandle); SAFE_DELETE(mpRefCount);
}
}
}template<typename ResType>
void ResHandle<ResType>::addRef()
{
if (mHandle != )
{
++(*mpRefCount);
}
}template<typename ResType>
ResHandle<ResType>::ResHandle() :
mHandle(),
mpRefCount()
{}template<typename ResType>
void ResHandle<ResType>::init(uint index)
{
assert(isNull());
assert(index <= MAX_INDEX); static uint sAutoMagic = ; if (++sAutoMagic > MAX_MAGIC)
{
sAutoMagic = ;
} mIndex = index;
mMagic = sAutoMagic; if (mpRefCount == )
{
mpRefCount = new uint;
}
*mpRefCount = ;
}template<typename ResType>
ResHandle<ResType>::operator uint() const
{
return mHandle;
}template<typename ResType>
bool ResHandle<ResType>::isNull() const
{
return !mHandle;
}template<typename ResType>
uint ResHandle<ResType>::getHandle() const
{
return mHandle;
}template<typename ResType>
uint ResHandle<ResType>::getMagic() const
{
return mMagic;
}template<typename ResType>
uint ResHandle<ResType>::getIndex() const
{
return mIndex;
}//-------------------------------------------------------------------template < typename Tag>
inline bool operator != (ResHandle<Tag> l, ResHandle<Tag> r)
{
return (l.getHandle() != r.getHandle());
}template < typename Tag>
inline bool operator == (ResHandle<Tag> l, ResHandle<Tag> r)
{
return (l.getHandle() == r.getHandle());
}
下一篇: Oracle 数据库SQL
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,089
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,566
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,415
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,187
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,823
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,906