为啥在获取系统时间时在这里使用`atomic_signal_fence`

Posted

技术标签:

【中文标题】为啥在获取系统时间时在这里使用`atomic_signal_fence`【英文标题】:Why a `atomic_signal_fence` is used here when getting system time为什么在获取系统时间时在这里使用`atomic_signal_fence` 【发布时间】:2018-06-26 13:13:11 【问题描述】:

我在实现无锁队列的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 语句都被重新排序,它似乎对精度没有影响。

【问题讨论】:

仅供参考:这里有很多关于旧系统的警告和QueryPerformanceCounter msdn.microsoft.com/en-us/library/windows/desktop/… 这可能是一种修复/解决方法的尝试。 【参考方案1】:

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

expensive1(); // takes a lot of time

SystemTime t = getSystemTime();

expensive2();

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

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

但至少这种方法似乎并没有太大的危害。 std::atomic_signal_fence(std::memory_order_seq_cst) 阻止编译器重新排序,但它不会产生 CPU 围栏指令。

【讨论】:

以上是关于为啥在获取系统时间时在这里使用`atomic_signal_fence`的主要内容,如果未能解决你的问题,请参考以下文章

为啥我在运行 Python 时在 Spyder 中收到“启动内核时发生错误”?

提交表单时在控制器中获取空值

为啥我在安装sql2005时在解决那个com功能警告时在dos时为啥显示msdtc不是内部命令啊 怎么解决?

为啥在使用 Promise 时在类方法中未定义“this”? [复制]

为啥在设置 Mongoose 连接时在 .then() 中使用 console.log() 时不打印?

为啥在使用动态变量名时在 Sparklyr 中加 1 实际上加 2?