std::atomic::fetch_add()
(或atomic_fetch_add()
在 C11 中)基于二进制补码对有符号整数进行运算。这与通常的有符号整数算法不同,后者允许使用其他表示方案。
来自N3337 [atomics.types.operations/30]:
备注:对于有符号整数类型,算术定义为使用二进制补码表示。没有未定义的结果。对于地址类型,结果可能是未定义的地址,但操作没有未定义的行为。
我的问题是:
(1) 在使用除二进制补码以外的有符号整数表示的平台上如何std::atomic::fetch_add()
实现? 是否只有使用互斥锁等的非无锁实现?
(2) 当在一个使用二进制补码以外的表示方法的平台上读取包含负值的原子变量的值时,它是否会自动转换为平台的本机格式?还是用户有责任将其转换为本机表示,因为二进制补码表示的位串是从中读取的?
std::atomic<int> a{0};
a.fetch_sub(1);
int x = a.load(); // The value of a is -1 (0xffffffff), so what is the value of x?
(3)我想知道在采用除二进制补码之外的表示方案的平台上的实现示例std::atomic::fetch_add()
(或atomic_fetch_add()
)。(如果这样的平台不存在,我不会感到惊讶!)
请注意,N2427对上述内容作出了如下规定:
正常的有符号整数加法运算在发生溢出时具有未定义的行为。对于原子变量,这种未定义的行为会带来很大的负担,因为通常没有办法预先测试溢出。我们认识到现代系统的实际行为,并定义原子提取和添加(减法)以使用二进制补码算法,而不是让溢出保持未定义状态。我们知道没有一个 C++ 实现会因为这个定义而出现问题。
(这个问题是基于学术兴趣。我问这个问题并不是因为我在面对任何实际问题时遇到了困难。)