我对静态断言有问题。静态断言完全是这样的:
static_assert(std::atomic<bool>::is_always_lock_free);该代码在Raspberry Pi 3( 4.19.118-v7+ #1311SMP Mon 27 14:21:24BST 2020 armv7l GNU/Linux)上失败。
在自由参考站点上,声明:
如果此原子类型始终是无锁的,则等于true,如果它从未或有时是无锁的,则等于false。这个常量的值与定义的宏ATOMIC_xxx_LOCK_FREE、成员函数is_lock_free和非成员函数std::atomic_is_lock_free都是一致的。
对我来说,第一件奇怪的事是“有时没有锁”。这取决于什么?但稍后再提问,回到问题上。
我做了个小测试。编写了以下代码:
#include <iostream>
#include <atomic>
int main()
{
std::atomic<bool> dummy {};
std::cout << std::boolalpha
<< "ATOMIC_BOOL_LOCK_FREE --> " << ATOMIC_BOOL_LOCK_FREE << std::endl
<< "dummy.is_lock_free() --> " << dummy.is_lock_free() << std::endl
<< "std::atomic_is_lock_free(&dummy) --> " << std::atomic_is_lock_free(&dummy) << std::endl
<< "std::atomic<bool>::is_always_lock_free --> " << std::atomic<bool>::is_always_lock_free << std::endl;
return 0;
}使用g++ -std=c++17 atomic_test.cpp && ./a.out (g++ 7.3.0和8.3.0,但这不重要)编译并在覆盆子上运行它,并得到:
ATOMIC_BOOL_LOCK_FREE --> 1
dummy.is_lock_free() --> true
std::atomic_is_lock_free(&dummy) --> true
std::atomic<bool>::is_always_lock_free --> false正如你所看到的,它并不像在can站点上声明的那样一致.作为比较,我用g++ 7.5.0在我的笔记本电脑(Ubuntu18.04.5)上运行了它,得到了:
ATOMIC_BOOL_LOCK_FREE --> 2
dummy.is_lock_free() --> true
std::atomic_is_lock_free(&dummy) --> true
std::atomic<bool>::is_always_lock_free --> true所以ATOMIC_BOOL_LOCK_FREE的值和is_always_lock_free常数是有区别的。
c++/8/bits/atomic_lockfree_defines.h: #define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE
c++/8/atomic: static constexpr bool is_always_lock_free = ATOMIC_BOOL_LOCK_FREE == 2;ATOMIC_BOOL_LOCK_FREE (或__GCC_ATOMIC_BOOL_LOCK_FREE)等于1或2之间有什么区别?它是这样的情况,如果1,那么它可能或不可能是无锁的,如果2,它是100%无锁?除了0,还有其他值吗?这是否是cppreference上的一个错误,其中声明所有这些返回值都应该是一致的?raspberry pi输出的结果中哪一个是真实的?
发布于 2020-10-07 23:52:19
在标准中,1的意思是“有时是免费的”。但实际上这意味着“在编译time".时不知道是无锁的”
在没有编译器选项的情况下,GCC的默认基线包括太老的ARM芯片,以至于它们不支持原子RMWs的必要指令,因此它必须生成可以在古老CPU上运行的代码,总是调用libatomic函数,而不是内联原子操作。
运行时查询函数在RPi及其ARMv7或ARMv8 CPU上运行时返回true。
使用-march=native或-mcpu=cortex-a53,您将得到is_always_lock_free为真,因为在编译时就知道目标机器确实支持所需的指令。(这些选项告诉GCC创建一个可能不会在其他/旧CPU上运行的二进制文件。)这是经“任择议定书”在评论中确认。
如果没有该编译选项,std::atomic操作必须调用lib原子函数,因此即使在现代的CPU上也会有额外的开销。
GCC (和所有正常的编译器)实现std::atomic<T>的方式,要么对所有实例都是免费的,要么没有锁,而不是在每个对象运行时检查对齐或其他任何东西。
alignof( std::atomic<int64_t> )是8,即使alignof( int64_t )在32位机器上只有4,所以如果你有一个对齐的原子对象,它就是未定义的行为。( UB的实际症状可能包括撕裂,即非原子性,用于纯负载和纯存储。)如果您遵循C++规则,那么所有原子对象都将对齐;只有当您将指向atomic<int64_t> *的指针转换错对齐并尝试使用它时,才会出现问题。
发布于 2020-10-07 10:39:21
ATOMIC_xxx_LOCK_FREE宏意味着:
0。1,这些原子类型有时是无锁的。2。因此,在您的PI环境中,std::atomic<bool>有时是无锁的,而您正在测试的dummy实例是无锁的,这意味着所有实例都是无锁的。
bool std::atomic_is_lock_free( const std::atomic<T>* obj )
在任何给定的程序执行中,对于同一类型的所有指针,无锁查询的结果都是相同的。
唯一的缺点是,在运行程序之前,您不知道该类型是否是无锁的。
If(not std::atomic_is_lock_free(&dummy)) {
std::cout << "Sorry, the program will be slower than expected\n";
}https://stackoverflow.com/questions/64242067
复制相似问题