在C ++ 11生效时,我正在尝试确定std::call_once
是否在Visual Studio 2013及以下版本中正常工作。示例如下所示。
// C++ source file
std::once_flag flag;
int main()
{
std::call_once(flag, []() {
// ...
});
}
Microsoft Support For C++11/14/17 Features似乎没有讨论std::call_once
。我不确定它是否取决于Dynamic Initialization and Destruction with Concurrency。虽然它是核心语言功能,但直到VS2015才提供它。
我的问题是,std::call_once
将在大多数Windows版本(XP及更高版本)和大多数支持C ++ 11的Visual Studio(VS 2010及更高版本)下运行吗?如果没有,那么使用它的要求是什么?
答案 0 :(得分:1)
这不是来自Visual Studio(这只是UI shell),而是来自您使用的CRT版本,并且是在CRT中实现的。如果你的代码编译和链接 - 实现。 call_once
中声明<mutex>
并在内部调用
int __CLRCALL_PURE_OR_CDECL _Execute_once(
once_flag& _Flag, _Lambda_fp_t _Lambda_fp, void *_Pv)
(来自VC\crt\src\stl\xonce.cpp
) - 此函数调用
BOOL WINAPI __crtInitOnceExecuteOnce(
__inout PINIT_ONCE InitOnce,
__in PINIT_ONCE_FN InitFn,
__inout_opt PVOID Parameter,
__out LPVOID* Context
);
与windows api InitOnceExecuteOnce
具有相同的签名(可从Vista 获取)
__crtInitOnceExecuteOnce
实现(如果你使用静态lib - libcpmt
将嵌入到你的PE中,或者如果使用动态链接CRT则会嵌入到msvcp*.dll
的dll中) - 首先看看是kernel32。 dll导出InitOnceExecuteOnce
如果是 - 只需调用此api并退出。如果它没有导出(XP情况)__crtInitOnceExecuteOnce
使用自己的原始实现
(如果并发中的多个线程使用相同的once_flag
调用此api - 直到“获胜者”线程将进行初始化(在InitOnceCallback函数(或lambda)内部,其他线程将在Sleep(0)
的自旋锁循环中等待
所以这个设计也适用于XP,并且可以正常工作