前篇
在对象池的使用上,我采用了一前写的一个数组模拟链表的结构,并且做了修改。最大的发现就是,STL的偏特化特性导致空间不能配置的去NEW它,而VECTOR的标准结构里是将这一块隐藏起来的,用户只要不停的PUSH。不过解决的方法当然有,代码修改后丑陋了点:
ListOfArray.h的代码
#pragma once #include <assert.h> /** V0.2 2010/04/15 重新考虑了下add这个东西,赋值是一个operate = 的操作。如果你的类里有许多对象,那么按照C++对象的原则,你要为每个对象的 operate进行重写。这显然很烦琐,那么链表的使用上,自然的要以存储轻巧的对象来进行辅佐操作。那么这次在我做的一个内存定位中, 数组里的空间(ELEMENT ElementData[llist_size])在申明的时候已经有了个固定的ID,虽然也可以外部在弄一个,然后operate=,不过 几番思量下,直接暴露一个专门的地址出来,进行操作,方便得多。同时对整个类也进行了一些重构: 1.对一些名字进行了调整 2.因为配置的需要,加入new的方式 3.考虑到STL偏特化特点,加入一个参数,表示手动的给予参数,还是自动的使用llist_size v0.1 *原理很简单,将数组的元素看成是链表,或者说是数组空间起到了内存池的作用。然后用两个结点表示 *当前使用/空闲的链表. *链表的增加从头部增加 *连表以公用的NULL结尾 * *对效率的一些说明 *增:这个无需说,链表直接秒杀。 *删:类里提供的是一个ELEMENT结构,里面包含了用户的数据。如果你想保持常量的效率 *在一些数据接口提供是,也必须用ELEMENT,这样才能记住结点信息。否则你可以单开个你自己数据类型的接口 *但是在删除时,就必须遍历(删除方法见提供的实例) *ELEMENT类型的快速使用:typedef CListOfArray<type, 1000>::ELEMENT CListOfArray_t; *你维护好CListOfArray_t就行 **/ template<typename llist_t, int llist_size=100, bool bManual=false> class CListOfArray { //variable public: struct ELEMENT { llist_t element; ELEMENT* pPre; ELEMENT* pNext; }; private: int nMaxElementItem; ELEMENT *ElementData/*[llist_size]*/;//数组空间 ELEMENT ElementFreeHead; //空余的指针链头 ELEMENT ElementUseHead; //当前使用的指针链头 int nFreeSum; int nUseSum; //function public: CListOfArray() { nMaxElementItem = llist_size; if( false == bManual ) { InitList(); } } ~CListOfArray() { delete []ElementData; } void ManualAlloct(int nManualMaxItem) { nMaxElementItem = nManualMaxItem; InitList(); } bool Add(const llist_t e); ELEMENT* GetMallocElement() { return MallocElement(); } ELEMENT* Erase(ELEMENT *p) { return ReleaseElement(p); } void Empty(); ELEMENT* GetListUseHead() { return ElementUseHead.pNext; } ELEMENT* GetListFreeHead() { return ElementFreeHead.pNext; } int GetSumElementUse() { return nUseSum; } int GetSumElementFree() { return nFreeSum; } private: void InitList(); ELEMENT* MallocElement(); ELEMENT* ReleaseElement(ELEMENT *p); // //加到头部 void AddNodeToList(ELEMENT* const pNode, ELEMENT* const pDesListHead) { pNode->pNext = pDesListHead->pNext; pNode->pPre = pDesListHead; // //链表以NULL结尾,表示无节点。比如linux的list这里是做成循环的 if( NULL!=pDesListHead->pNext ) { pDesListHead->pNext->pPre = pNode; } pDesListHead->pNext = pNode; } }; /** *这里是大函数体定义 **/ template <typename llist_t, int llist_size, bool bManual> void CListOfArray<llist_t, llist_size, bManual>::InitList() { assert( nMaxElementItem>0 ); ElementData = new ELEMENT[nMaxElementItem]; nUseSum = 0; nFreeSum = llist_size; //开始串指针 for(int i=0; i<nMaxElementItem-1; ++i) { ElementData[i].pNext = &ElementData[i+1]; } ElementData[nMaxElementItem-1].pNext = NULL; ElementUseHead.pNext = NULL; ElementFreeHead.pNext = &ElementData[0]; } template <typename llist_t, int llist_size, bool bManual> typename CListOfArray<llist_t, llist_size, bManual>::ELEMENT* CListOfArray<llist_t, llist_size, bManual>::MallocElement() { //判断是否有空余元素 if( NULL==ElementFreeHead.pNext ) { return NULL; } --nFreeSum; ++nUseSum; //从Free链中脱出,头部 ELEMENT* p = ElementFreeHead.pNext; ElementFreeHead.pNext = ElementFreeHead.pNext->pNext; AddNodeToList(p, &ElementUseHead); return p; } template <typename llist_t, int llist_size, bool bManual> typename CListOfArray<llist_t, llist_size, bManual>::ELEMENT* CListOfArray<llist_t, llist_size, bManual>::ReleaseElement( ELEMENT *p) { --nUseSum; ++nFreeSum; ELEMENT *pResult = p->pNext; //从Use链中脱离 p->pPre->pNext = p->pNext; //判断是否是尾元素 if( NULL!=p->pNext ) { p->pNext->pPre = p->pPre; } AddNodeToList(p, &ElementFreeHead); return pResult; } template <typename llist_t, int llist_size, bool bManual> bool CListOfArray<llist_t, llist_size, bManual>::Add(const llist_t e) { //先从Free指针里取得一个空节点 ELEMENT *p = MallocElement(); if( NULL==p ) { return false; } else { p->element = e; return true; } } template <typename llist_t, int llist_size, bool bManual> void CListOfArray<llist_t, llist_size, bManual>::Empty() { // //最快捷方法是将ElementUseHead直接连到ElementFreeHead末尾。考虑到平常使用不多,Empty仅是测试使用 //暂时不重写,保持用Erase ELEMENT* p = GetListHead(); while( NULL!=p ) { p = Erase(p); continue; p=p->pNext; } }
Main文件的调用代码:
// HelloTest.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "ListOfArray.h" const int MAX_TESTOBJECT_ITEM = 100; const int MAX_MANUAL_TESTOBJECT_ITEM = 100; class CNet { public: bool bEnable; int nIdenti; private: public: CNet() { bEnable = false; } private: }; class CLogic { public: bool bEnable; int nIdenti; private: public: CLogic() { bEnable = false; } private: }; typedef CListOfArray<CNet,MAX_TESTOBJECT_ITEM, true> CListOfArrayT; typedef CListOfArray<CNet,MAX_TESTOBJECT_ITEM, true>::ELEMENT CListOfArray_t; // // void PrintListInfo(CListOfArrayT *pNetList) { cout<<"PrintListInfo--------:"<<endl; cout<<"SumUse:"<<pNetList->GetSumElementUse()<<endl; cout<<"SumFree:"<<pNetList->GetSumElementFree()<<endl; } bool Connect(CListOfArrayT *pNetList, CLogic *pLogicArray) { CListOfArray_t *pGetNetItem = pNetList->GetMallocElement(); if( NULL==pGetNetItem ) { return false; } pGetNetItem->element.bEnable = true; pLogicArray[ pGetNetItem->element.nIdenti ].bEnable = true; return true; } void DisConnect(CListOfArrayT *pNetList, CLogic *pLogicArray) { int nSumUse = pNetList->GetSumElementUse(); CListOfArray_t *pGetNetItem = pNetList->GetListUseHead(); if( 0==nSumUse ) { // //没有节点了 return; } int nErase = rand()%nSumUse; for(int i=0; i<nErase; ++i) { pGetNetItem = pGetNetItem->pNext; } pGetNetItem->element.bEnable = false; pLogicArray[ pGetNetItem->element.nIdenti ].bEnable = false; pNetList->Erase(pGetNetItem); } void TestStep1( CListOfArrayT *pNetList, CLogic *pLogicArray, int nCount) { for(int i=0; i<nCount; ++i) { if( false==Connect(pNetList, pLogicArray)) { cout<<"step 1 Connect Full"<<endl; } } } void TestStep2( CListOfArrayT *pNetList, CLogic *pLogicArray, int nCount) { for(int i=0; i<nCount; ++i) { int j=rand()%2; if( 0==j ) { //增加 if( false==Connect(pNetList, pLogicArray)) { cout<<"step 2 Connect Full"<<endl; } } else { //随机删除 DisConnect(pNetList, pLogicArray); } } } void VerifyEnable(CListOfArrayT *pNetList, CLogic *pLogicArray) { cout<<"VerifyEnable--------:"<<endl; // //进行个数比对 int nSumNetList = pNetList->GetSumElementUse(); int nSumLogicArray = 0; for(int i=0; i<MAX_TESTOBJECT_ITEM; ++i) { if( true==pLogicArray[i].bEnable ) { nSumLogicArray++; } } cout<<"nSumNetList:"<<nSumNetList<<endl; cout<<"nSumLogicArray:"<<nSumLogicArray<<endl; // //进行Identi比对 int nLogicArrayIndex; CListOfArray_t *pGetNetUseItem = pNetList->GetListUseHead(); CListOfArray_t *pGetNetFreeItem = pNetList->GetListFreeHead(); for(; NULL!=pGetNetUseItem; pGetNetUseItem=pGetNetUseItem->pNext) { nLogicArrayIndex = pGetNetUseItem->element.nIdenti; if( pGetNetUseItem->element.bEnable!=pLogicArray[nLogicArrayIndex].bEnable ) { cout<<nLogicArrayIndex<<" error!!!!!"<<endl; } } for(; NULL!=pGetNetFreeItem; pGetNetFreeItem=pGetNetFreeItem->pNext) { nLogicArrayIndex = pGetNetFreeItem->element.nIdenti; if( pGetNetFreeItem->element.bEnable!=pLogicArray[nLogicArrayIndex].bEnable ) { cout<<nLogicArrayIndex<<" error!!!!!"<<endl; } } } int _tmain(int argc, _TCHAR* argv[]) { srand( (unsigned)time( NULL ) ); int i; CListOfArrayT NetList; CLogic LogicArray[MAX_TESTOBJECT_ITEM]; NetList.ManualAlloct(MAX_TESTOBJECT_ITEM); // //ID初试化 CListOfArray_t *pListItem = NetList.GetListFreeHead(); for(i=0; i<MAX_TESTOBJECT_ITEM; ++i) { pListItem->element.nIdenti = i; LogicArray[i].nIdenti = i; pListItem = pListItem->pNext; } TestStep1(&NetList, LogicArray, 982); TestStep2(&NetList, LogicArray, 3000); TestStep1(&NetList, LogicArray, 910); TestStep2(&NetList, LogicArray, 600); TestStep2(&NetList, LogicArray, 760); // //结果ID比对 VerifyEnable(&NetList, LogicArray); // //查看分布情况 PrintListInfo(&NetList); PrintArrayInfo(LogicArray); return 0; }
我在调用中,模拟了一个连接进来后,从网络对象中取得对象,然后对比的也从上层的逻辑中取得。原理很简单,一个序列化的ID。 Main里的代码主要是比对2个对象集合间的值是否一一对应。目前暂时没发现什么BUG,欢迎提交