c++ - 为什么在获取系统时间时使用 `atomic_signal_fence`

标签 c++ concurrency atomic barrier

我在 github repo 中找到了这个函数它实现了无锁队列。此函数使用QueryPerformanceCounter来获取准确的系统时间。

#define CompilerMemBar() std::atomic_signal_fence(std::memory_order_seq_cst)
SystemTime getSystemTime()
{
    LARGE_INTEGER t;
    CompilerMemBar();
    if (!QueryPerformanceCounter(&t)) {
        return static_cast<SystemTime>(-1);
    }
    CompilerMemBar();

    return static_cast<SystemTime>(t.QuadPart);
}

我注意到有两个CompilerMemBar(),我认为这是为了防止编译器重新排序。然而,在我在 github 上搜索了一些代码后,我发现用编译器屏障包装 QueryPerformanceCounter 可能并不常见。所以我的问题是这里的这些障碍是为了处理一些特殊情况吗?可能可能的重新排序会影响我们得到的系统时间的精度?但我不知道他们会怎么做,因为我认为即使是 WINAPI 调用或 return 语句被重新排序,它似乎对精度没有影响。

最佳答案

代码开发人员可能认为,如果编译器无法对语句重新排序,将会产生更准确的结果。 例如:

expensive1(); // takes a lot of time

SystemTime t = getSystemTime();

expensive2();

如果您希望在两个昂贵的调用之间获得准确的时间戳(或性能计数),则不希望编译器使用其中一个对 getSystemTime() 进行重新排序 因为它可能会影响 QueryPerformanceCounter 返回的值。

这是否现实,我不知道。编译器必须知道函数内部发生了什么,否则它不会重新排序任何内容 (如果在预编译库中定义了昂贵调用,则无论如何都不会发生语句重新排序)。

但至少这种做法看起来并没有造成太大的危害。 std::atomic_signal_fence(std::memory_order_seq_cst) 阻止编译器重新排序,但它不会生成 CPU 栅栏指令。

关于c++ - 为什么在获取系统时间时使用 `atomic_signal_fence`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48304781/

相关文章:

java - 如何使用 objectify 确保 Appengine 实体上的并发请求的一致性?

python - 序列解包是原子的吗?

validation - 一种检查行不存在并将其插入原子的常用方法?

c++ - 原子读取是否保证读取到最新值?

c++ - 抽象基类调用父类的纯虚函数

C++ 静态数组声明

c++ - 如何使用 OpenCV 检测大量白色像素的区域?

c中的并发变量访问

java - Spring集成ServiceActivators的并发性

c++ - 做两个用户定义的转换