天天看點

對象記憶體池技術

  在這裡 ,還是先介紹下我們這邊對象記憶體池技術的基本概念和設計過程:   所謂的對象記憶體池技術設計過程如下: 首先為某種對象預先生成若幹個空閑對象 ,并且使用對象管理類進行管理。應用程式在需要使用此對象時,即向管理對象申請空閑對象.管理對象即檢視對象記憶體池,如果發現存在未使用空閑對象,即配置設定給申請者。如果發現已無空閑對象,可自行擴充對象記憶體池,并且滿足申請對象的需求,也可以直接傳回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進行鎖定,保證每次隻有一個線程操作對象池。