在什么情况下您希望将
std::atomic<T>
或 std::atomic_flag
标记为 volatile
(如果有的话)?
中断处理程序中使用的
std::atomic_flag
怎么样?需要标记为volatile
吗?
我发现的主要用例是在调试器/内存转储中提供一些数据,同时允许稍后在后台日志记录线程中收集。
例如,这是一个这样的程序,我们可以跟踪是否发生异常。
static volatile std::atomic<bool> HAD_EXCEPTION{false};
void foo()
{
try
{
bar();
}
catch (...)
{
HAD_EXCEPTION.store(true, std::memory_order_relaxed);
}
}
// Maybe this gets added later or it requires some optional logging dependency.
#ifdef ENHANCED_LOGGING
void report()
{
if (HAD_EXCEPTION.exchange(false, std::memory_order_seq_cst))
{
LOG("foo encountered an exception!");
}
}
#endif
如果没有 volatile,Clang 通常会完全忽略
HAD_EXCEPTION
变量,这是标准所允许的,假设由于 as-if 规则而未定义
ENHANCED_LOGGING
。然而,通过添加 volatile,它对 std::atomic<bool>
的所有成员变量施加了波动性约束,包括它实际存储在内存中的任何位置,即使编译器看起来从未读取过它。