基于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());
}

游戏引擎基于Handle的资源管理的更多相关文章

  1. 转:高层游戏引擎——基于OGRE所实现的高层游戏引擎框架

    高层游戏引擎——基于OGRE所实现的高层游戏引擎框架 这是意念自己的毕业论文,在一个具体的实践之中,意念主要负责的是物件和GUI之外的其他游戏系统.意念才学疏陋,望众位前辈不吝赐教.由于代码质量不高. ...

  2. 游戏引擎架构 (Jason Gregory 著)

    第一部分 基础 第1章 导论 (已看) 第2章 专业工具 (已看) 第3章 游戏软件工程基础 (已看) 第4章 游戏所需的三维数学 (已看) 第二部分 低阶引擎系统 第5章 游戏支持系统 (已看) 第 ...

  3. 对HGE游戏引擎的一次封装

    HGE游戏引擎是一个开源2D游戏引擎,基于directX. 它的渲染及逻辑是基于帧回调的框架模式, 其提供一些主要的图像操作和输入控制功能. 我在之前写一个2D游戏的时候对它整个框架进行了一次封装,非 ...

  4. Android游戏引擎总汇 原文出处:http://software.intel.com/en-us/blogs/2012/03/13/game-engines-for-android?page=1

    随着Android系统的使用越来越广泛,了解一下Android平台下的游戏引擎就非常有必要.而同时因为基于Intel x86的移动设备越来越多,我也非常关注支持x86的移动游戏引擎.然而就目前为止游戏 ...

  5. Atitit 基于dom的游戏引擎

    Atitit 基于dom的游戏引擎 1. 添加sprite控件(cocos,createjs,dom)1 1.1.1. Cocos1 1.1.2. createjs1 1.1.3. Dom模式2 1. ...

  6. 浅析游戏引擎的资源管理机制——扒一扒Unity3D中隐藏在背后的资源管理

    游戏中通常有大量资源,如网格.材质.纹理.动画.着色器程序和音乐等,游戏引擎作为做游戏的工具,自然要提供良好的资源管理,让游戏开发者用最简单的方式使用资源.游戏引擎的资源管理包括两大部分:离线资源管理 ...

  7. 推荐一款基于XNA的开源游戏引擎《Engine Nine》

    一.前沿导读 XNA是微软基于.Net部署的下一代3D/2D游戏开发框架,其实XNA严格来说类似下一代的DirectX,当然不是说XNA会取代DirectX,但是基于XNA我们对于面向XBOX360, ...

  8. 基于Java的开源3D游戏引擎jMonkeyEngine

    jMonkeyEngine简介 jMonkeyEngine是一款纯Java语言编写的游戏引擎,继承了Java应用跨平台的特性,而且是开放源代码的,遵循BSD开源协议,BSD开源协议用一句简单的话概括就 ...

  9. 开源免费的HTML5游戏引擎

    青瓷引擎的成长 青瓷引擎自2015年4月项目启动开始,7月首次亮相2015年ChinaJoy,便得到业界的极大关注,随后开启限量测试,收到数百个开发者团队的试用申请及反馈,期间经历了18个内测版本,完 ...

随机推荐

  1. Redis 在 Java 中的使用

    转:http://blog.csdn.net/jiangtao_st/article/details/8256610 一.下载jar包 https://github.com/xetorthio/jed ...

  2. 【C语言天天练(十一)】深入理解指针

    引言:在C语言中.指针的地位是不言而喻的,要想非常好的掌握C语言,掌握指针是必须的,这也是C语言不同于其它语言的地方. (一)指针的指针 样例: int i; int *pi;/*把pi初始化为指向变 ...

  3. 全国天气预报数据API调用PHP示例

    本代码示例是基于PHP的聚合数据全国天气预报API服务请求的代码样例,使用前你需要: ①:通过https://www.juhe.cn/docs/api/id/39 申请一个天气预报API的appkey ...

  4. vue.js+koa2项目实战(四)搭建koa2服务端

    搭建koa2服务端 安装两个版本的koa 一.版本安装 1.安装 koa1 npm install koa -g 注:必须安装到全局 2.安装 koa2 npm install koa@2 -g 二. ...

  5. 微软Azure公有云个人用户是否能支付得起?

    个人建立自己的站点是普通"白领"的愿望.由于,我们的大脑分泌的脑汁须要排泄渠道.怎么办呢? 依据微软公有云的公开报价(Pricing),租用单核CPU.0.75GB内存,20GB硬 ...

  6. iOS UITableViewDelegate && UITableViewDataSource 执行顺序

    #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableV ...

  7. Java NIO之Charset类字符编码对象

    介绍 java中使用Charset来表示编码对象 This class defines methods for creating decoders and encoders and for retri ...

  8. VMware厚置备延迟置零,厚置备置零,精简置备具体解释

    本文具体介绍VMware厚置备延迟置零,厚置备置零,精简置备的概念及选择使用 1.厚置备延迟置零(zeroed thick) 以默认的厚格式创建虚拟磁盘.创建过程中为虚拟磁盘分配所需空间.创建时不会擦 ...

  9. Urho3D 在Win10下编辑器崩溃的解决方案

    本解决方案来自于 https://github.com/urho3d/Urho3D/issues/2417 描述 在Win10中通过CMake启用URHO_ANGELSCRIPT选项的前提下生成Urh ...

  10. java.util.Date和java.sql.Date之间的转换

    java.util.Date是在除了SQL语句的情况下面使用的.java.sql.Date是针对SQL语句使用的,它只包含日期而没有时间部分它 们都有getTime方法返回毫秒数,自然就可以直接构建. ...