天天看点

对象内存池技术

  在这里 ,还是先介绍下我们这边对象内存池技术的基本概念和设计过程:   所谓的对象内存池技术设计过程如下: 首先为某种对象预先生成若干个空闲对象 ,并且使用对象管理类进行管理。应用程序在需要使用此对象时,即向管理对象申请空闲对象.管理对象即检视对象内存池,如果发现存在未使用空闲对象,即分配给申请者。如果发现已无空闲对象,可自行扩充对象内存池,并且满足申请对象的需求,也可以直接返回NULL,表明对象申请失败。在程序获取对象并且使用后,想释放此对象资源时。继续想管理对象提出申请释放对象,管理对象接受到释放对象后将其再次放入对象池,成为可使用对象。   看了上面的介绍后,接下来以伪代码的方式来更加清晰的展现对象获取和释放的过程。     申请对象 OBJ*  ApplyObj(void) {     if 存在空闲对象     {         OBJ *pIdleObj = NULL;         pIdleObj = GetIdleObj(); //获取空闲对象         return pIdleObj;     }    //不存在空闲对象,处理方式如下     方式1:     ExtendObjectPool();        //扩充对象池     OBJ *pIdleObj = NULL;     pIdleObj = GetIdleObj();  //获取空闲对象     return pIdleObj;     方法2:     return NULL; }   释放对象 void ReleaseObj(OBJ* pObj) {     if(pObj!=NULL)     {         AddToObjectPool(pObj);   //对象再次加入到对象池     } }   有了上面的这些说明,我想大家对于对象内存池技术应该都有了一个大概了解吧! (其实没有什么高深的技术,只是一些简单的应用,大家用一个平常心来看待就可以了!)接下介绍具体来实现这个对象内存池,我们需要做些什么?   在实现对象内存池之前,先提出几个我们需要达到的目标:   u        对象内存池管理对象具有广泛的通用性,也就是说能够满足应用程序生成各个不同的对象池,例如:P layer对象池、Monster对象池、NPC对象池。 u        产生对象的速度一定要快于直接使用 new/delete或者malloc/free方式很多倍。 u        对象池容量具有可扩展性和纠错能力。也就是说在无空闲对象时,管理对象类能够自动生成一批新的空闲对象供上层使用,同时能够正确指出目前所使用对象是否为合法对象池对象。 u        对象的申请和释放,必须具备多线程安全性。也就是说在服务器程序通过各个不同线程同时访问对象池管理时,能够保证合法获取和释放池对象。     基于上面这些问题条件,这里先提供几种简单易行的解决方案来供大家参考。其他解决方案还有很多,我也就不一一列举了!靠大家独立思考和发挥了。: )   解决方案1:(单链表实现) u        第一步,分配模板对象数组,并且用指针保存。 u        第二步,建立一单链表管理类,将已经分配成功的数组对象,分配到 单链表中,同时设置表头和表尾指针。 u        第三步,从对象池中申请对象,首先检测链表中是否存在可使用空闲对象。如果没有可返回 NULL,也可以先锁定扩充链表(保存扩展对象数组指针)。然后返回可使用对象给用户。 u        第四步,释放对象池对象时,首先将表尾指针指向被释放对象,接下来被回收对象为此链表表尾。完成释放过程。 u        最后,内存释放, delete数组指针。 图例演示如下:   解决方案2:(双链表实现) u        为了能够使我们建立的对象池能够在应用程序中通用,我们考虑使用模板 template<class OBJ>来生成我们的class CObjectPool. u        为了能够快速获取对象,我们采用双向链表的方式来建立我们的对象池。对象获取从当前链表头开始进行,对象释放直接加到链表尾。操作过程中需要使用一附加指针对象表明当前可使用对象位置。若此指针为 NULL,表明已无可使用空闲对象。 u        为了生成一个一定容量的对象池,我们可以通过模板的方式也可以通过初始化 Init方式来生成初始对象池。在申请过程中无空闲对象,需要向系统重新一定数目对象,并且按照顺序加到链表尾。实现对象池的可扩充性。 u        为了保证多线程安全,我们在对象申请和释放过程中加入 Lock进行锁定,保证每次只有一个线程操作对象池。