为什么在获取系统时间时这里使用 `atomic_signal_fence`
Why a `atomic_signal_fence` is used here when getting system time
我在实现无锁队列的 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
.
返回的值
这是否现实,我不知道。编译器必须知道函数内部发生了什么,否则它不会重新排序任何东西
(如果 expensive
调用是在 pre-compiled 库中定义的,则无论如何都不会对语句进行重新排序)。
但至少这种做法似乎没有太大害处。
std::atomic_signal_fence(std::memory_order_seq_cst)
阻止编译器重新排序,但它不会生成 CPU 围栏指令。
我在实现无锁队列的 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
.
这是否现实,我不知道。编译器必须知道函数内部发生了什么,否则它不会重新排序任何东西
(如果 expensive
调用是在 pre-compiled 库中定义的,则无论如何都不会对语句进行重新排序)。
但至少这种做法似乎没有太大害处。
std::atomic_signal_fence(std::memory_order_seq_cst)
阻止编译器重新排序,但它不会生成 CPU 围栏指令。