`

IOCP分层二,一个复杂度为1的对象池定位

阅读更多

前篇

IOCP的分层一

 

 

在对象池的使用上,我采用了一前写的一个数组模拟链表的结构,并且做了修改。最大的发现就是,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,欢迎提交

1
0
分享到:
评论

相关推荐

    IOCP 内存池线程池的一个例子

    结合这两个概念,"IOCP 内存池线程池"意味着在一个基于IOCP的系统中,线程池中的工作线程使用了内存池来管理用于收发I/O操作的内存缓冲区。这样的设计能显著提升网络服务、数据库服务器等需要大量并发I/O操作的应用...

    iocp开发一个最简单的例子

    本篇文章将通过一个最简单的IOCP示例,深入探讨其工作原理和使用方法。 首先,我们来看看IOCP的基本概念。IOCP是Windows系统提供的一种I/O模型,它允许应用程序通过单一的线程池来处理所有的I/O完成事件,极大地...

    C#面向对象的IOCP模板类

    面向对象的IOCP(I/O完成端口)模板类在C#编程中是一个高效的设计模式,主要用于处理大量的并发I/O操作。IOCP是Windows操作系统提供的一种异步I/O模型,它能够有效地处理大量并发的网络连接,从而提高服务器的性能和...

    iocp 一个实现不错的类

    1. **创建I/O完成端口**:使用`CreateIoCompletionPort`函数创建,可以为一个文件句柄或网络套接字关联到IOCP,以便后续的I/O操作完成后,结果会被发送到这个端口。 2. **提交I/O请求**:通过调用`TransmitFile`、`...

    iocpserver.rar_IOCP_IOCPServer_内存池_完成端口_线程池

    综上所述,IOCPServer.rar 包含的项目是一个精心设计的服务器实现,它利用了 Windows 平台上的 I/O 完成端口技术,配合线程池和内存池策略,旨在提供一个高度优化、可扩展的服务器解决方案。开发者可以通过分析和...

    一个简单的IOCP模型的服务器

    1. **创建IOCP**:首先,服务器需要调用`CreateIoCompletionPort`函数创建一个IOCP对象。这个对象是所有后续I/O操作的中心。 2. **绑定Socket到IOCP**:服务器需要为每个监听套接字和连接套接字绑定到IOCP上,这样...

    IOCP完成端口+多线程池.zip

    总的来说,这个压缩包中的内容可能是实现了一个基于IOCP和多线程池的高效并发服务,可以用于处理大量并发的网络连接,如服务器端的应用程序。通过深入研究这些源代码,我们可以学习到如何在实际应用中有效地利用这两...

    VC的IOCP开发,iocp类,demo

    IOCP是Windows系统内核提供的一个同步I/O管理对象,它允许多个线程等待同一组I/O操作的完成。当I/O操作完成后,系统会将完成信息放入IOCP,等待的线程可以从IOCP中取出这些信息并进行后续处理。这种设计使得服务器...

    一个自己调试和测试过的IOCP库

    1. **创建Completion Port**:程序首先创建一个Completion Port对象,所有的I/O操作都会关联到这个Port上。 2. **创建Socket并绑定到IOCP**:创建Socket后,通过`CreateIoCompletionPort`函数将Socket与IOCP关联...

    IOCP.NET(强大的IOCP托管库)

    当一个I/O请求发起后,系统会将该请求挂起,并在I/O操作完成后唤醒一个等待的线程,而不是为每个I/O请求创建新的线程。这种设计减少了线程上下文切换的开销,提升了系统的整体性能。 ### 2. IOCP.NET库的核心功能 ...

    Delphi IOCP简单实例

    1. 初始化IOCP,创建一个IOCP对象。 2. 创建或获取需要进行异步I/O操作的句柄(如套接字),并将其与IOCP关联。 3. 使用异步I/O函数发起读写操作,设置好`OVERLAPPED`结构。 4. 创建并启动线程池,线程将不断地从...

    IOCP核心类

    IOCP的基本工作原理是这样的:当一个I/O操作开始时,不会立即阻塞当前线程,而是将其请求放入完成端口,然后由系统调度其他线程来处理完成后的结果。这种方式使得线程可以立即返回执行其他任务,而无需等待I/O操作...

    一个对IOCP进行封装的DLL

    标题中的“一个对IOCP进行封装的DLL”指的是一个动态链接库(DLL)文件,它将Windows操作系统中的I/O完成端口(I/O Completion Port,简称IOCP)进行了抽象和封装,使得开发者无需深入理解底层的IOCP机制,也能利用...

    IOCP原理windows下实现

    1. **创建IOCP**:首先,需要调用`CreateIoCompletionPort`函数创建一个IOCP对象。这个对象用于存储和管理所有与之关联的I/O操作完成信息。 2. **关联设备或套接字**:接着,将需要进行I/O操作的设备(如硬盘)或套...

    IOCP简明教程

    IO Completion Port...通过CreateIoCompletionPort函数来创建一个IOCP对象,这个函数的原型为HANDLE CreateIoCompletionPort(HANDLE FileHandle, HANDLE ExistingCompletionPort, ULONG_PTR CompletionKey, DWORD ...

    IOCP服务器模块.rar

    2. 完成端口:IOCP是一个系统对象,用于接收已完成的I/O操作通知,从而调度相应的处理线程。 3. 工作线程池:IOCP通过工作线程池来处理完成的I/O请求,线程池中的线程数量可以根据系统负载动态调整。 二、IOCP...

    windows iocp网络通讯库封装

    总结来说,"windows iocp网络通讯库封装"是一个利用Windows IOCP技术构建的C++网络通信库,它通过`ITcpClient`和`ITcpServer`接口为开发者提供了简单易用的客户端和服务器端功能,同时借助`libsocket.dll`和`...

    iocp.zip_IOCP

    1. **完成端口对象**:IOCP是系统创建的一个对象,用于接收和管理完成的I/O操作。应用程序通过CreateIoCompletionPort函数创建并关联到特定的设备或套接字。 2. **提交I/O请求**:使用诸如TransmitFile、WSASend、...

    一个简单的IOCP服务器/客户端类

    在本项目中,我们有一个简单的IOCP服务器和客户端类实现,这将帮助我们理解如何利用IOCP来构建高性能的网络服务。 1. **IOCP基本概念** - I/O模型:包括同步I/O、异步I/O和完成端口I/O等。IOCP是异步I/O的一种高效...

Global site tag (gtag.js) - Google Analytics