std :: call_once在VS2013及以下版本下工作吗?

时间:2017-03-26 18:43:08

标签: windows visual-studio c++11

在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及更高版本)下运行吗?如果没有,那么使用它的要求是什么?

1 个答案:

答案 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,并且可以正常工作