IO完成端口与线程池

具体情况参考《windows核心编程》第五版的第十章第十一章

(Vista以上)

MSDN示例http://msdn.microsoft.com/en-us/library/windows/desktop/ms686980(v=vs.85).aspx


IO完成端口

1.创建空的IO完成端口,保存其句柄。

CompletePort = CreateIoCompletionPort(
         INVALID_HANDLE_VALUE,
         NULL,
         NULL,
         0);

2.创建工作线程,将IO完成端口传入

// Create threads.
     for(int i=0; i<SystenInfo.dwNumberOfProcessors*2; i++)
     {
         HANDLE hThread = CreateThread(NULL,
             0,
             IOCPWorkThread,
             CompletePort,
             0,
             NULL);

         CloseHandle(hThread);
     }

3.在本进程的任意线程中,关联IOCP与IO设备,进行IO操作。。

 if ((CreateIoCompletionPort((HANDLE)IO设备句柄,CompetionPort,(DWORD)KEY,0)) == NULL)

    {

      printf("CreateIoCompletionPort failed with error%d"n",GetLastError());

      return 0;

    }

    IO操作

4.在工作线程中,等待IOCP中某个请求完成。

while (TRUE)

 {

...

      if (GetQueuedCompletionStatus(ComplectionPort,&BytesTransferred,(LPDWORD)&KEY,      (LPOVERLAPPED*)&PerIOData,INFINITE) == 0)

          {

            printf("GetQueuedCompletionStatus failed with error%d"n",GetLastError());

            return 0;

    }

    switch (KEY)

    {

    //某个IO操作已完成。

    ...

    }

...

}

5.(可选)使用PostQueuedCompletionStatus模拟IO操作。工作线程可以通过GetQueuedCompletionStatus获得模拟的IO操作的完成通知。

例如可以在用户取消操作时,模拟几(工作线程数)IO操作。工作线程获得该操作完成的通知后,退出线程。



----------------------------------------------------------------------

线程池作用

1:以异步方式调用函数
2:每隔一段时间调用一个函数
3:在内核对象触发时调用一个函数(可用于非窗口程序的计时器)
4:在异步I/O请求完成时调用一个函数


只关注4.

1.创建IO线程池并关联IO设备。
PTP_IO WINAPI CreateThreadpoolIo(
  __in         HANDLE fl,//我们打开的io设备句柄 //Overlapped flag
  __in         PTP_WIN32_IO_CALLBACK pfnio,
  __inout_opt  PVOID pv,
  __in_opt     PTP_CALLBACK_ENVIRON pcbe
);
2.声明一个回调函数,传给1中的第二个参数。
VOID CALLBACK IoCompletionCallback(
  __inout      PTP_CALLBACK_INSTANCE Instance,
  __inout_opt  PVOID Context,
  __inout_opt  PVOID Overlapped,
  __in         ULONG IoResult,
  __in         ULONG_PTR NumberOfBytesTransferred,
  __inout      PTP_IO Io
);
3.每次IO操作前,关联线程池内部的IO完成端口。
VOID WINAPI StartThreadpoolIo(
  __inout  PTP_IO pio//1中返回的线程池句柄
);
4.IO操作返回错误码不是IO_ERROR_PENDING时,或者IO操作的结果不需要再被关注时:

使线程池停止调用回调函数

VOID WINAPI CancelThreadpoolIo(
  __inout  PTP_IO pio//1中返回的线程池句柄
);
5.(可选)在其他线程中等待IO操作完成(调用回调函数之前进行)。

VOID WINAPI WaitForThreadpoolIoCallbacks(
  __inout  PTP_IO pio,
  __in     BOOL fCancelPendingCallbacks//是否调用回调函数。
);

6.(可选)回调函数的终止操作。

---------------

-------------------------------------------------------------------

对线程池进行定制(可选):

7.自定义线程池。

7.1

(使用InitializeThreadpoolEnvironment函数创建PTP_CALLBACK_ENVIRON pcbe参数,传递给

CreateThreadpoolIo,线程池加入默认清理组
7.2

// Initialize the private thread pool
   g_pThreadPool = CreateThreadpool(NULL);

// Change  min=2 / max=4 thread pool parameters
   SetThreadpoolThreadMaximum(g_pThreadPool, 4);
   SetThreadpoolThreadMinimum(g_pThreadPool, 2);

   // Reset the callback environment
   // Note: this is an inline function from winbase.h
   //       that calls TpInitializeCallbackEnviron() in winnt.h.
   //       --> 
   //       CallbackEnviron->Version = 1;
   //       CallbackEnviron->Pool = NULL;
   //       CallbackEnviron->CleanupGroup = NULL;
   //       CallbackEnviron->CleanupGroupCancelCallback = NULL;
   //       CallbackEnviron->RaceDll = NULL;
   //       CallbackEnviron->ActivationContext = NULL;
   //       CallbackEnviron->FinalizationCallback = NULL;
   //       CallbackEnviron->u.Flags = 0;
   InitializeThreadpoolEnvironment(&g_callbackEnvironment);


   // Associate our private thread pool with the callback environment
   // Note: this is an inline function from winbase.h
   //       that calls TpSetCallbackThreadpool() in winnt.h.
   //       --> 
   //       CallbackEnviron->Pool = Pool;
   SetThreadpoolCallbackPool(&g_callbackEnvironment, g_pThreadPool);  

...

...使用线程池

...


8.自定义的线程池(7.1)需要得体的销毁(7.2中,调用CloseThreadPoolXXXX时,对应的线程池从默认清理组移除)。

8.1 首先使用CreateThreadpoolCleanupGroup创建一个清理组。


8.2 然后使用SetThreadpoolCallbackCleanupGroup将清理组与一个或者多个线程池绑定。

该函数的第三个参数是一个回调函数,将在清理组被取消的时候调用。

8.3 销毁线程池。

VOID WINAPI CloseThreadpoolCleanupGroupMembers(
  __inout      PTP_CLEANUP_GROUP ptpcg,
  __in         BOOL fCancelPendingCallbacks,//是否取消 已经提交但尚未处理的IO操作。。
  __inout_opt  PVOID pvCleanupContext
);
如果第二个参数是true,则会调用8.2中的回调函数。

如果第二个参数是true,则第三个参数无用。

8.4 

释放清理组资源

VOID WINAPI CloseThreadpoolCleanupGroup(
  __inout  PTP_CLEANUP_GROUP ptpcg
);

销毁清理组环境变量

VOID DestroyThreadpoolEnvironment(
  __inout  PTP_CALLBACK_ENVIRON pcbe
);

关闭线程池

VOID WINAPI CloseThreadpool(
  __inout  PTP_POOL ptpp
);



  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值