-
DIOCP开源项目出炉,附带<IOCP退出资料的管控研究代码>
添加时间:2013-5-18 点击量:经过对一段时候对IOCP的进修和研究。对IOCP的流程有了必然的懂得。
后面对一段时候的IOCP优化和实际项目标应用,在DIOCP中参加了日记文件记录功能,哄骗api编写了一个客户端通信类,等解决了很多bug,并已应用在公司的项目中,现运行稳定。今天对IOCP退出时资料的开释,做了最后一步研究和优化。
为了便利大师进修,我把这个项目定名为DIOCP,上传在google的SVN项目中
https://code.google.com/p/diocp/
大师可以经由过程svn代码,里面我写了一个Echo的测试Demo,筹办后续参加聊天等Demo。
特地为DIOCP开设了一个群:320641073,迎接进修的IOCP的童鞋进入评论辩论。
--IOCP退出资料的管控研究
如今在项目中应用的IOCP退出的过程是。
procedure TIOCPConsole.close;
begin
//封闭办事端端口
FIOCPObject.closeSSocket;
//停止
stopListener;
//断开所有连接
FIOCPObject.DisconnectAllClientContext;
//守候资料的回归
FIOCPObject.WaiteForResGiveBack;
//停止工作线程
stopWorkers;
//标记状况
FActive := false;
end;
对IO内存池也进行了一些优化,首要参加了资料回归的监控
unit uMemPool;
interface
uses
JwaWinsock2, Windows, SyncObjs, uIOCPProtocol;
type
TIODataMemPool = class(TObject)
private
//全部偿还的旌旗灯号灯
FCanCloseSingle: THandle;
FCs: TCriticalSection;
//第一个可用的内存块
FHead: POVERLAPPEDEx;
//最后一个可用的内存卡
FTail: POVERLAPPEDEx;
//可用的内存个数
FUseableCount:Integer;
//正在应用的个数
FUsingCount:Integer;
/// <summary>
/// 将一个内存块添加到尾部
/// </summary>
/// <param name=pvIOData> (POVERLAPPEDEx) </param>
procedure AddData2Pool(pvIOData:POVERLAPPEDEx);
/// <summary>
/// 获得一块可以应用的内存
/// </summary>
/// <returns> POVERLAPPEDEx
/// </returns>
function getUsableData: POVERLAPPEDEx;
/// <summary>
/// 创建一块内存空间
/// </summary>
/// <returns> POVERLAPPEDEx
/// </returns>
function InnerCreateIOData: POVERLAPPEDEx;
procedure clearMemBlock(pvIOData:POVERLAPPEDEx);
//开释所有的内存块
procedure FreeAllBlock;
public
class function instance: TIODataMemPool;
constructor Create;
destructor Destroy; override;
function waiteForGiveBack: Boolean;
//借一块内存
function borrowIOData: POVERLAPPEDEx;
//换会一块内存
procedure giveBackIOData(const pvIOData: POVERLAPPEDEx);
function getCount: Cardinal;
function getUseableCount: Cardinal;
function getUsingCount:Cardinal;
end;
implementation
uses
uIOCPFileLogger;
var
__IODATA_instance:TIODataMemPool;
constructor TIODataMemPool.Create;
begin
inherited Create;
FCs := TCriticalSection.Create();
FUseableCount := 0;
FUsingCount := 0;
FCanCloseSingle := CreateEvent(nil, True, True, nil);
end;
destructor TIODataMemPool.Destroy;
begin
CloseHandle(FCanCloseSingle);
FreeAllBlock;
FCs.Free;
inherited Destroy;
end;
{ TIODataMemPool }
procedure TIODataMemPool.AddData2Pool(pvIOData:POVERLAPPEDEx);
begin
if FHead = nil then
begin
FHead := pvIOData;
FHead.next := nil;
FHead.pre := nil;
FTail := pvIOData;
end else
begin
FTail.next := pvIOData;
pvIOData.pre := FTail;
FTail := pvIOData;
end;
Inc(FUseableCount);
end;
function TIODataMemPool.InnerCreateIOData: POVERLAPPEDEx;
begin
Result := POVERLAPPEDEx(GlobalAlloc(GPTR, sizeof(OVERLAPPEDEx)));
GetMem(Result.DataBuf.buf, MAX_OVERLAPPEDEx_BUFFER_SIZE);
Result.DataBuf.len := MAX_OVERLAPPEDEx_BUFFER_SIZE;
//清理一块内存
clearMemBlock(Result);
end;
function TIODataMemPool.borrowIOData: POVERLAPPEDEx;
begin
FCs.Enter;
try
Result := getUsableData;
if Result = nil then
begin
//临盆一个内存块
Result := InnerCreateIOData;
//直接借走<增长应用计数器>
Inc(FUsingCount);
end;
//变成没有旌旗灯号
if FUsingCount > 0 then
ResetEvent(FCanCloseSingle);
finally
FCs.Leave;
end;
end;
procedure TIODataMemPool.clearMemBlock(pvIOData: POVERLAPPEDEx);
begin
//清理一块内存
pvIOData.IO_TYPE := 0;
pvIOData.WorkBytes := 0;
pvIOData.WorkFlag := 0;
//ZeroMemory(@pvIOData.Overlapped, sizeof(OVERLAPPED));
//还原大小<分派时的大小>
pvIOData.DataBuf.len := MAX_OVERLAPPEDEx_BUFFER_SIZE;
//ZeroMemory(pvIOData.DataBuf.buf, pvIOData.DataBuf.len);
end;
procedure TIODataMemPool.FreeAllBlock;
var
lvNext, lvData:POVERLAPPEDEx;
begin
lvData := FHead;
while lvData <> nil do
begin
//记录下一个
lvNext := lvData.next;
//开释当前Data
FreeMem(lvData.DataBuf.buf, lvData.DataBuf.len);
GlobalFree(Cardinal(lvData));
//筹办开释下一个
lvData := lvNext;
end;
FHead := nil;
FTail := nil;
FUsingCount := 0;
FUseableCount := 0;
end;
function TIODataMemPool.getCount: Cardinal;
begin
Result := FUseableCount + FUsingCount;
end;
procedure TIODataMemPool.giveBackIOData(const pvIOData:
POVERLAPPEDEx);
begin
FCs.Enter;
try
if (pvIOData.pre <> nil) or (pvIOData.next <> nil) or (pvIOData = FHead) then
begin
TIOCPFileLogger.logErrMessage(收受接管内存块是呈现了异常,该内存块已经收受接管!);
end else
begin
//清理内存块
clearMemBlock(pvIOData);
//参加到可以应用的内存空间
AddData2Pool(pvIOData);
//削减应用计数器
Dec(FUsingCount);
end;
//有旌旗灯号
if FUsingCount = 0 then SetEvent(FCanCloseSingle);
finally
FCs.Leave;
end;
end;
function TIODataMemPool.getUsableData: POVERLAPPEDEx;
var
lvPre:POVERLAPPEDEx;
begin
if FTail = nil then
begin
Result := nil;
end else
begin
Result := FTail;
lvPre := FTail.pre;
if lvPre <> nil then
begin
lvPre.next := nil;
FTail := lvPre;
end else //FTail是第一个也是最后一个,只有一个
begin
FHead := nil;
FTail := nil;
end;
Result.next := nil;
Result.pre := nil;
Dec(FUseableCount);
Inc(FUsingCount);
end;
end;
function TIODataMemPool.getUseableCount: Cardinal;
begin
Result := FUseableCount;
end;
function TIODataMemPool.getUsingCount: Cardinal;
begin
Result := FUsingCount;
end;
class function TIODataMemPool.instance: TIODataMemPool;
begin
Result := __IODATA_instance;
end;
function TIODataMemPool.waiteForGiveBack: Boolean;
var
lvRet:DWORD;
begin
Result := false;
lvRet := WaitForSingleObject(FCanCloseSingle, INFINITE);
if lvRet = WAIT_OBJECT_0 then
begin
Result := true;
end;
end;
initialization
__IODATA_instance := TIODataMemPool.Create;
finalization
if __IODATA_instance <> nil then
begin
__IODATA_instance.Free;
__IODATA_instance := nil;
end;
end.
所有随风而逝的都属于昨天的,所有历经风雨留下来的才是面向未来的。—— 玛格丽特·米切尔 《飘》