std::atomic 智能指针的部分模板特化

Partial template specialization of std::atomic for smart pointers

背景

自 C++11 起,std::shared_ptr 上的原子操作可以通过 std::atomic_... 找到的方法 here 完成,因为如下所示的部分特化是不可能的:

std::atomic<std::shared_ptr<T>>

这是因为 std::atomic 仅接受 TriviallyCopyable 类型,并且 std::shared_ptr(或 std::weak_ptr)不可简单复制。

但是,从 C++20 开始,这些方法已被弃用,并被 std::atomic 用于 std::shared_ptr 的部分模板专业化所取代,如 here 所述。

问题

我不确定

  1. 为什么 std::atomic_... 被替换了。
  2. 用于启用 std::atomic 智能指针的部分模板专业化的技术。

针对 atomic<shared_ptr> 或类似性质的一些提议解释了多种原因。特别值得注意的是 P0718,它告诉我们:

The C++ standard provides an API to access and manipulate specific shared_ptr objects atomically, i.e., without introducing data races when the same object is manipulated from multiple threads without further synchronization. This API is fragile and error-prone, as shared_ptr objects manipulated through this API are indistinguishable from other shared_ptr objects, yet subject to the restriction that they may be manipulated/accessed only through this API. In particular, you cannot dereference such a shared_ptr without first loading it into another shared_ptr object, and then dereferencing through the second object.

N4058 解释了关于您必须如何实施此类事情的性能问题。由于 shared_ptr 的大小通常大于单个指针,因此原子访问通常必须使用自旋锁来实现。因此,要么每个 shared_ptr 实例都有一个自旋锁,即使它从未被原子地使用过,要么这些原子函数的实现必须为单个对象提供 table 自旋锁。或者使用全局自旋锁。

None 如果你有一个专用于原子的类型,这些都是问题。

atomic<shared_ptr> 实现可以使用 atomic<T> 的常用技术,当 T 太大而不适合 CPU 原子操作时。他们通过法令绕过 TriviallyCopyable 限制:标准要求它们存在并且是原子的,所以实现就是这样。 C++ 实现不必遵循与常规 C++ 程序相同的规则。