5.2.4 std::atomic:指针运算

5.2.4 std::atomic:指针运算

原子指针类型,可以使用内置类型或自定义类型T,通过特化 std::atomic<T*> 进行定义,就 如同使用bool类型定义 std::atomic<bool> 类型一样。虽然接口几乎一致,但是它的操作是对于相关的类型的指针,而非bool值本身。就像 std::atomic<bool> ,虽然它既不能拷贝构造,也不能拷贝赋值,但是他可以通过合适的类型指针进行构造和赋值。如同成员函数 is_lock_free()一样,std::atomic<T*>也有load(), store(), exchange(), compare_exchange_weak()和compare_exchage_strong()成员函数,与  std::atomic<bool> 的语义相同,获取与返回的类型都是T*,而不是bool。

std::atomic<T*>为指针运算提供新的操作。基本操作有fetch_add()fetch_sub()提供,它们在存储地址上做原子加法和减法,为+=, -=, ++和--提供简易的封装。对于内置类型的操作, 如你所预期:如果x是 std::atomic<Foo*> 类型的数组的首地址,然后x+=3让其偏移到第四个 元素的地址,并且返回一个普通的 Foo* 类型值,这个指针值是指向数组中第四个元素。 fetch_add()和fetch_sub()的返回值略有不同(所以x.ftech_add(3)让x指向第四个元素,并且函 数返回指向第一个元素的地址)。这种操作也被称为“交换-相加”,并且这是一个原子的“读-改- 写”操作,如同exchange()和compare_exchange_weak()/compare_exchange_strong()一样。 正像其他操作那样,返回值是一个普通的 T* 值,而非是std::atomic<T*>对象的引用,所以 调用代码可以基于之前的值进行操作:

class Foo {};

Foo some_array[5];
std::atomic<Foo*> p(some_array);
Foo* x = p.fetch_add(2); // p加2,并返回原始值
assert(x == some_array);
assert(p.load() == &some_array[2]);
x = (p-=1);   // p减1,并返回原始值
assert(x == &some_array[1]);
assert(p.load() == &some_array[1]);

函数也允许内存顺序语义作为给定函数的参数:

p.fetch_add(3, std::memory_order_release);

因为fetch_add()和fetch_sub()都是“读-改-写”操作,它们可以拥有任意的内存顺序标签,以及加入到一个释放序列中。指定的语序不可能是操作符的形式,因为没办法提供必要的信息: 这些形式都具有memory_order_seq_cst语义。

剩下的原子类型基本上都差不多:它们都是整型原子类型,并且都拥有同样的接口(除了相关的内置类型不一样)。下面我们就看看这一类类型。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值