Window下高性能IOCP模型队列多线程下应用

           IOCP,先从概念上认识一下。IOCP全称I/O Completion Port,中文译为I/O完成端口。是Windows平台最高效的I/O模块,现在IIS服务器,就采用IOCP模型。IOCP是一个异步I/O的API,它可以高效地将I/O事件通知给应用程序。与使用select()或是其它异步方法不同的是,现在很多书,文字都直接将IOCP模块和网络编程关联起来,好像IOCP就是和网络打交道的。典型的IOCP模型的使用,是 将一个套接字(socket)与一个完成端口关联了起来,当一个网络事件发生的时候,Windows将此完成端口加入一个队列中,然后应用程序可以对核心层进行查询以得到此完成端口。本文的重点,不是将网络编程,而是把IOCP当作队列来用。经测试,ICOP模型队列,是如此的高效,让人惊叹!

          先认识一下IOCP模型三个重要的API函数。IOCP模型队列,是先进先出。先投递,先被通知,适合多线程下工作。

DelphiXE,Windows下三个函数原型。

//创建IOCP完成端口句柄

function CreateIoCompletionPort(FileHandle, ExistingCompletionPort: THandle;
  CompletionKey, NumberOfConcurrentThreads: DWORD): THandle; stdcall;

//获取IOCP事件
function GetQueuedCompletionStatus(CompletionPort: THandle;
  var lpNumberOfBytesTransferred, lpCompletionKey: DWORD;
  var lpOverlapped: POverlapped; dwMilliseconds: DWORD): BOOL; stdcall;

//投递IOCP事件
function PostQueuedCompletionStatus(CompletionPort: THandle; dwNumberOfBytesTransferred: DWORD;
  dwCompletionKey: DWORD; lpOverlapped: POverlapped): BOOL; stdcall;
{$EXTERNALSYM PostQueuedCompletionStatus}

 

下面是实现代码:

 

unit IOCPQueue;

interface

uses windows, classes;

type

  TOnQueueProc = procedure(sender: tobject; ParamA, ParamB: integer) of object;

  TIOCPQueue = class
  private
    FCompletionPort: THandle;
    FOnQueueProc: TOnQueueProc;
    FOverlapped: Overlapped;
    procedure Run;
  public
    constructor create(OnQueueProc: TOnQueueProc);
    destructor Destroy; override;
    procedure PostQueueState(ParamA, ParamB: integer);
    procedure Close;
  end;

implementation
  uses SysUtils;


{ TIOCPQueuue }

//Post关闭消息
procedure TIOCPQueue.Close;
begin
  PostQueuedCompletionStatus(FCompletionPort, 0, 0, @FOverlapped);
end;

//创建完成端口
constructor TIOCPQueue.create;
begin
  FOnQueueProc := OnQueueProc;
  FCompletionPort := CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
  if FCompletionPort = 0 then
    raise Exception.Create('TIOCPQueue Create Error FCompletionPort=0');

    TThread.CreateAnonymousThread(Run).Start;
end;

//关闭完成端口句柄
destructor TIOCPQueue.Destroy;
begin
  Close;
  CloseHandle(FCompletionPort);
  inherited;
end;

//提交完成端口消息
procedure TIOCPQueue.PostQueueState(ParamA, ParamB: integer);
begin
  PostQueuedCompletionStatus(FCompletionPort, ParamA, ParamB, nil);
end;

//查询完成端口,状态
procedure TIOCPQueue.Run;
var
  Transfered: DWORD;
  {$IF RTLVersion > 22.0} //XE2,XE3
   key: NativeUInt    ;
  {$ELSE}
   key: DWORD;
  {$IFEND}
  o: POverlapped;
  ret: bool;
begin
  while true do
  begin
    ret := GetQueuedCompletionStatus(FCompletionPort, Transfered,
      key, POverlapped(o), INFINITE);
    if ret then
    begin
      if o = nil then
        FOnQueueProc(self, Transfered, key)
      else
        break;
    end;
  end;
end;

end.

posted @ 2014-06-15 11:04  发烧践行者  阅读(1906)  评论(0编辑  收藏  举报