} } }

    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 <> nilor (pvIOData.next <> nilor (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.


    所有随风而逝的都属于昨天的,所有历经风雨留下来的才是面向未来的。—— 玛格丽特·米切尔 《飘》
    分享到: