我在问题中引用的博客文章的后续文章中讨论了这一点。如果由于某种原因您不能使用boost::call_once
块范围的静态是指针、POD 或具有线程安全的构造函数,您可以编写 GCC 发出的相同初始化保护代码:
// Define a static local variable once, safely, for MSVC
//
// This macro is necessary because MSVC pre-2013 doesn't
// properly implement C++11 static local initialization.
// It is equivalent to writing something like
//
// static type var = stmt;
//
// in a compliant compiler (e.g. GCC since who knows when)
// States for lock checking
enum { uninitialized = 0, initializing, initialized };
// Preprocessor hackery for anonymous variables
#define PASTE_IMPL(x, y) x ## y
#define PASTE(x, y) PASTE_IMPL(x, y)
#define ANON_VAR(var) PASTE(var, __LINE__)
#define STATIC_DEFINE_ONCE(type, var, stmt) \
static type var; \
static int ANON_VAR(state); \
bool ANON_VAR(cont) = true; \
while (ANON_VAR(cont)) { \
switch (InterlockedCompareExchange(&ANON_VAR(state), \
initializing, uninitialized)) { \
case uninitialized: \
var = stmt; \
InterlockedExchange(&ANON_VAR(state), initialized); \
ANON_VAR(cont) = false; \
break; \
case initializing: \
continue; \
case initialized: \
ANON_VAR(cont) = false; \
break; \
} \
} do { } while (0)
你可以像这样使用它
void concurrently_accessed() {
STATIC_DEFINE_ONCE(int, local_var, thread_unsafe_initializer());
// ...
}
这种方法利用了 C 语言标准所要求的静态块范围变量的零初始化。上述宏将让您安全地使用“魔法”静态,直到MSVC 2014提供实际的编译器和运行时支持。