C++ 为什么在获取系统时间时在这里使用“原子信号围栏”
我在实现无锁队列的中找到了此函数。此函数使用C++ 为什么在获取系统时间时在这里使用“原子信号围栏”,c++,concurrency,atomic,barrier,C++,Concurrency,Atomic,Barrier,我在实现无锁队列的中找到了此函数。此函数使用QueryPerformanceCounter获取准确的系统时间 #define CompilerMemBar() std::atomic_signal_fence(std::memory_order_seq_cst) SystemTime getSystemTime() { LARGE_INTEGER t; CompilerMemBar(); if (!QueryPerformanceCounter(&t)) {
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);
}
定义编译器mbar()标准::原子信号围栏(标准::内存顺序)
SystemTime getSystemTime()
{
大整数t;
编译器mbar();
if(!QueryPerformanceCounter(&t)){
返回静态_cast(-1);
}
编译器mbar();
返回静态_型铸件(t.QuadPart);
}
我注意到有两个
编译器mbar()
,我认为这是为了防止编译器重新排序。然而,在我在github上搜索了一些代码之后,我发现使用编译器屏障包装QueryPerformanceCounter
可能不是一种常见的做法。所以我的问题是这些障碍是用来处理一些特殊情况的?是否可能重新排序会影响我们获得的系统时间精度?但是我不知道他们会怎么做,因为我认为即使WINAPI调用或return语句被重新排序,它似乎对精度没有影响。代码开发人员可能认为,如果编译器不能重新排序语句,它将产生更准确的结果。。
例如:
expensive1(); // takes a lot of time
SystemTime t = getSystemTime();
expensive2();
如果希望在两个昂贵调用之间获得准确的时间戳(或性能计数),则不希望编译器对其中一个调用重新排序getSystemTime()
因为它可能会影响QueryPerformanceCounter
返回的值
我不知道这是否现实。编译器必须知道函数内部发生了什么,否则它不会对任何内容重新排序
(如果在预编译库中定义了昂贵的
调用,则不会对语句进行重新排序)
但至少这种方法似乎没有造成多大危害。
std::atomic\u signal\u fence(std::memory\u order\u seq\u cst)
阻止编译器重新排序,但它不会生成CPU fence指令。fyi:这里有很多关于旧系统和QueryPerformanceCounter
的注意事项,这可能是一种修复/解决方法的尝试。