多线程情况下初始化一次(InitOnceExecuteOnce)
2017-04-13 15:25
696 查看
下面的例子展示了如何使用一次初始化(one-time initialization)
回调函数中的初始化代码. 如果回调函数执行成功,
并且通过lpContext 变量返回.
如果函数调用成功, 代码通过检查 fPending 变量的值来决定是否创建一个事件对象句柄或返回另外一个线程创建的句柄. 如果 fPending变量 为FALSE,则证明初始化已经完成,因此
和调用InitOnceComplete 函数去完成这次初始化操作.
如果调用InitOnceComplete 函数成功,
如果初始化操作被另外一个线程完成,
下面的例子展示了如何使用一次初始化(one-time initialization)
同步
在这个例子中, 全局变量g_InitOnce是one-time initialization结构体.它被初始化为INIT_ONCE_STATIC_INIT值.
OpenEventHandleSync函数返回唯一的事件句柄. 它通过调用InitOnceExecuteOnce 函数去执行包含在
InitHandleFunction
回调函数中的初始化代码. 如果回调函数执行成功,
OpenEventHandleAsync通过lpContext变量返回事件对象句柄; 否则,返回INVALID_HANDLE_VALUE.
InitHandleFunction函数是 one-time initialization 回调函数.
InitHandleFunction调用CreateEvent 函数去创建一个事件对象句柄
并且通过lpContext 变量返回.
#define _WIN32_WINNT 0x0600 #include <windows.h> // Global variable for one-time initialization structure INIT_ONCE g_InitOnce = INIT_ONCE_STATIC_INIT; // Static initialization // Initialization callback function BOOL CALLBACK InitHandleFunction ( PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContext); // Returns a handle to an event object that is created only once HANDLE OpenEventHandleSync() { PVOID lpContext; BOOL bStatus; // Execute the initialization callback function bStatus = InitOnceExecuteOnce(&g_InitOnce, // One-time initialization structure InitHandleFunction, // Pointer to initialization callback function NULL, // Optional parameter to callback function (not used) &lpContext); // Receives pointer to event object stored in g_InitOnce // InitOnceExecuteOnce function succeeded. Return event object. if (bStatus) { return (HANDLE)lpContext; } else { return (INVALID_HANDLE_VALUE); } } // Initialization callback function that creates the event object BOOL CALLBACK InitHandleFunction ( PINIT_ONCE InitOnce, // Pointer to one-time initialization structure PVOID Parameter, // Optional parameter passed by InitOnceExecuteOnce PVOID *lpContext) // Receives pointer to event object { HANDLE hEvent; // Create event object hEvent = CreateEvent(NULL, // Default security descriptor TRUE, // Manual-reset event object TRUE, // Initial state of object is signaled NULL); // Object is unnamed // Event object creation failed. if (NULL == hEvent) { return FALSE; } // Event object creation succeeded. else { *lpContext = hEvent; return TRUE; } }
异步
在这个例子中, 全局变量g_InitOnce是one-time initialization结构体.它被初始化为INIT_ONCE_STATIC_INIT值.
OpenEventHandleAsync函数返回唯一的事件句柄.
OpenEventHandleAsync调用InitOnceBeginInitialize 函数进入初始化状态.
如果函数调用成功, 代码通过检查 fPending 变量的值来决定是否创建一个事件对象句柄或返回另外一个线程创建的句柄. 如果 fPending变量 为FALSE,则证明初始化已经完成,因此
OpenEventHandleAsync通过lpContext 变量返回事件对象句柄. 否则, 它调用CreateEvent 函数去创建一个事件对象句柄
和调用InitOnceComplete 函数去完成这次初始化操作.
如果调用InitOnceComplete 函数成功,
OpenEventHandleAsync函数返回新的事件对象句柄. 否则, 它关闭事件对象句柄和调用InitOnceBeginInitialize 函数并且传入参数INIT_ONCE_CHECK_ONLY 去决定是否初始化失败或者被另外一个线程完成.
如果初始化操作被另外一个线程完成,
OpenEventHandleAsync函数通过lpContext变量返回另外一个线程创建的事件对象句柄. 否则,返回INVALID_HANDLE_VALUE.
#define _WIN32_WINNT 0x0600 #include <windows.h> // Global variable for one-time initialization structure INIT_ONCE g_InitOnce = INIT_ONCE_STATIC_INIT; // Static initialization // Returns a handle to an event object that is created only once HANDLE OpenEventHandleAsync() { PVOID lpContext; BOOL fStatus; BOOL fPending; HANDLE hEvent; // Begin one-time initialization fStatus = InitOnceBeginInitialize(&g_InitOnce, // Pointer to one-time initialization structure INIT_ONCE_ASYNC, // Asynchronous one-time initialization &fPending, // Receives initialization status &lpContext); // Receives pointer to data in g_InitOnce // InitOnceBeginInitialize function failed. if (!fStatus) { return (INVALID_HANDLE_VALUE); } // Initialization has already completed and lpContext contains event object. if (!fPending) { return (HANDLE)lpContext; } // Create event object for one-time initialization. hEvent = CreateEvent(NULL, // Default security descriptor TRUE, // Manual-reset event object TRUE, // Initial state of object is signaled NULL); // Object is unnamed // Event object creation failed. if (NULL == hEvent) { return (INVALID_HANDLE_VALUE); } // Complete one-time initialization. fStatus = InitOnceComplete(&g_InitOnce, // Pointer to one-time initialization structure INIT_ONCE_ASYNC, // Asynchronous initialization (PVOID)hEvent); // Pointer to event object to be stored in g_InitOnce // InitOnceComplete function succeeded. Return event object. if (fStatus) { return hEvent; } // Initialization has already completed. Free the local event. CloseHandle(hEvent); // Retrieve the final context data. fStatus = InitOnceBeginInitialize(&g_InitOnce, // Pointer to one-time initialization structure INIT_ONCE_CHECK_ONLY, // Check whether initialization is complete &fPending, // Receives initialization status &lpContext); // Receives pointer to event object in g_InitOnce // Initialization is complete. Return handle. if (fStatus && !fPending) { return (HANDLE)lpContext; } else { return INVALID_HANDLE_VALUE; } }
相关文章推荐
- c++11 call_once用法(多线程时仅初始化一次的完美解决方案)
- 深入Pthread(四):一次初始化-pthread_once_t
- 初始化单链表,并在只遍历一次的情况下倒序
- 一次初始化-pthread_once_t pthread_once 函数
- init返回0说明初始化失败,其调用时间仅次与DllEntry,成多于一个的驱动程序实例时仅调用一次DllEntry,而xxx_Init会被调用多次,CreateFile与XXX_Open对应
- 深入Pthread(四):一次初始化-pthread_once_t
- 深入Pthread(四):一次初始化-pthread_once_t
- iOS开发- initWithFrame 和 initWithCoder 什么情况下会初始化?
- 【Boost】boost库中thread多线程详解8——call_once仅运行一次
- 深入Pthread(四):一次初始化-pthread_once_t
- 线程安全的单例模式 -- 使用pthread_once一次初始化
- 深入Pthread(四):一次初始化-pthread_once_t
- 使用THREAD_POOL.execute引发一次神奇的多线程问题
- 记录单例模式遇到多线程时的多种情况
- 修改commit的内容,包含最近一次,和任意某个commit两种情况
- linux-3.2.36内核启动4-setup_arch中的内存初始化3(arm平台 bootmem_init源码分析)
- 远端仓库初始化成裸仓库 git init --bare
- 浅析 Linux 初始化 init 系统,Systemd
- Android系统初始化脚本init.rc分析
- 一次 read by other session 的处理过程--数据走索引需要看索引字段的数据分布情况