我正在尝试确定当C++11生效时,std::call_once在Visual Studio2013及更低版本下是否如预期的那样工作。下面显示了一个示例。
// C++ source file
std::once_flag flag;
int main()
{
std::call_once(flag, []() {
// ...
});
}微软的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版本(VS2010及以上)下运行吗?如果不是,那么使用它的要求是什么?
发布于 2017-03-27 05:56:41
这不取决于Visual Studio (这只是UI shell),而取决于您使用的CRT版本,以及这是在CRT中实现的。如果您的代码已编译并链接实现。在<mutex>中声明的call_once和内部调用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这样的动态链接库中)-首先看一下kernel32.dll导出InitOnceExecuteOnce,如果是,只需调用这个接口并退出。如果没有导出(XP情况),__crtInitOnceExecuteOnce使用自己原语实现(如果并发中的几个线程使用相同的once_flag调用此api -直到"winner“线程将进行初始化(在InitOnceCallback函数(或λ)内),其他线程将在带有Sleep(0)的自旋锁循环中等待,因此此设计也适用于XP,并将工作
https://stackoverflow.com/questions/43033009
复制相似问题