• Chapter11"windows线程池" 之 内核对象触发调用回调函数


         众所周知,一般可以调用WaitForSingleObject、WaitForMultiObject来实现线程同步。但是当多个线程等待同一个内核对象变为触发态时,这并不是一种明智的做法,这样会浪费大量的系统资源。而windows线程池很有效提供系统性能。
         利用windows线程池实现,当内核对象变为触发态时,自动调用一个回调函数,一如既往的需要四步
    1. 创建对应的回调函数,回调函数必须符合如下原型
      VOID CALLBACK WaitCallback(
                      _Inout_      PTP_CALLBACK_INSTANCE Instance,
                      _Inout_opt_  PVOID Context,
                      _Inout_      PTP_WAIT Wait,
                      _In_         TP_WAIT_RESULT WaitResult // 表示WaitCallback函数被执行的原因
                                                             // WAIT_OBJECT_0 表示等待的内核对象变为触发态
                                                                              而执行WaitCallback
                                                             // WAIT_TIMEOUT 表示因为超时了
                                                                              而执行WaitCallback函数
                                                             // WAIT_ABANDONED_0 表示等待的内核对象被"抛弃"了。
                                 )
    2. 调用CreateThreadpoolWait函数创建对应的等待项
      PTP_WAIT WINAPI CreateThreadpoolWait(
        _In_         PTP_WAIT_CALLBACK pfnwa,//对应上面的WaitCallback函数
        _Inout_opt_  PVOID pv, //对应WaitCallback函数的第二个参数Context
        _In_opt_     PTP_CALLBACK_ENVIRON pcbe // WaitCallback函数的运行环境
      );
    3. 调用SetThreadpoolWait函数项线程池注册一个由CreateThreadpoolWait函数创建的 PTP_WAIT
      VOID WINAPI SetThreadpoolWait(
        _Inout_   PTP_WAIT pwa, // 由CreateThreadpoolWait函数创建的 PTP_WAIT
        _In_opt_  HANDLE h, // 等待的内核对象
        _In_opt_  PFILETIME pftTimeout // 最长的等待时间
      );
    4. 完成之后,调用 CloseThreadpoolWait 函数释放资源。
    #include <windows.h> 
    #include <iostream> 
    #include <time.h>
    
    VOID CALLBACK WaitCallback(
                               _Inout_      PTP_CALLBACK_INSTANCE Instance,
                               _Inout_opt_  PVOID Context,
                               _Inout_      PTP_WAIT Wait,
                               _In_         TP_WAIT_RESULT WaitResult
                               )
    { 
        printf("Wait: %s\n", Context);
    } 
    
    void   main() 
    { 
        HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        PTP_WAIT ptpWait[10];
        char *p[10];
        ULARGE_INTEGER ulRelativeStartTime;  
        ulRelativeStartTime.QuadPart = (LONGLONG) -(50000000); // 5秒
        FILETIME ftRelativeStartTime;  
        ftRelativeStartTime.dwHighDateTime = ulRelativeStartTime.HighPart;  
        ftRelativeStartTime.dwLowDateTime  = ulRelativeStartTime.LowPart;  
        
        for (int i = 0; i < 10; i++)
        {
            p[i] = new char[2];
            p[i][0] = '0' + i;
            p[i][1] = 0;
            ptpWait[i] = CreateThreadpoolWait(WaitCallback, p[i], NULL);
            SetThreadpoolWait(ptpWait[i], hEvent, &ftRelativeStartTime);
        }
    
        //如果在"5秒"内按下任意键,则后面的 SetEvent 函数会将 hEvent 变为触发态,并且没有 PTP_WAIT 过期,
        //    从10个 PTP_WORK 中任意选出一个激活,接着就会触发对应的WaitCallback函数
        //如果超过"5秒"才按下任意键,则所有的 PTP_WORK 都已过期,10 个 PTP_WAIT都会被激活,
        //    接着对应的 10 个 WaitCallback 函数会被执行。
        getchar();
        SetEvent(hEvent);
        getchar();
    
        //释放资源
        for (int i = 0; i < 10; i++)
        {
            CloseThreadpoolWait(ptpWait[i]);
            
            delete []p[i];
            p[i] = NULL;
        }
    
        printf("all the wait have been closed!\n");  
    } 
    《windows核心编程》(笔记)系列文章是本人看《windows核心编程》时的一些学习笔记,有疏忽之处,欢迎各位网友指正。QQ邮箱:job.zhanghui@qq.com

  • 相关阅读:
    网卡驱动引起openstack的mtu问题
    Ironic几种不同的场景下的网络拓扑
    enable multi-tenancy on openstack pike
    galera断电后无法重建集群
    Fabric单节点安装备忘
    OpenStack Ironic 常见问题
    Enable multi-tenancy on ironic
    kolla-ansible快速入门
    kolla管理openstack容器
    d2.js学习笔记(七)——动态SVG坐标空间
  • 原文地址:https://www.cnblogs.com/java20130722/p/3207100.html
Copyright © 2020-2023  润新知