简体   繁体   English

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

[英]Partial template specialization of std::atomic for smart pointers

Background背景

Since C++11, atomic operations on std::shared_ptr can be done via std::atomic_... methods found here , because the partial specialization as shown below is not possible:从 C++11 开始, std::shared_ptr上的原子操作可以通过std::atomic_...此处找到的方法完成,因为如下所示的部分特化是不可能的:

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

This is due to the fact that std::atomic only accepts TriviallyCopyable types, and std::shared_ptr (or std::weak_ptr ) is not trivially copyable.这是因为std::atomic只接受TriviallyCopyable类型,并且std::shared_ptr (或std::weak_ptr )不可简单复制。

However, as of C++20, these methods have been deprecated, and got replaced by the partial template specialization of std::atomic for std::shared_ptr as described here .但是,从 C++20 开始,这些方法已被弃用,并被std::atomicstd::shared_ptr的部分模板特化所取代,如here所述。

Question

I am not sure of我不确定

  1. Why std::atomic_... got replaced.为什么std::atomic_...被替换了。
  2. Techniques used to enable the partial template specialization of std::atomic for smart pointers.用于为智能指针启用std::atomic的部分模板特化的技术。

Several proposals for atomic<shared_ptr> or something of that nature explain a variety of reasons.一些关于atomic<shared_ptr>或类似性质的提议解释了各种原因。 Of particular note is P0718 , which tells us:特别值得注意的是P0718 ,它告诉我们:

The C++ standard provides an API to access and manipulate specific shared_ptr objects atomically, ie, without introducing data races when the same object is manipulated from multiple threads without further synchronization. C++ 标准提供了一个 API 来以原子方式访问和操作特定的shared_ptr对象,即在没有进一步同步的情况下从多个线程操作同一对象时不会引入数据竞争。 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.此 API 是脆弱且容易出错的,因为通过此 API 操作的shared_ptr对象与其他shared_ptr对象无法区分,但受到只能通过此 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.特别是,如果不先将此类shared_ptr加载到另一个shared_ptr对象中,然后通过第二个对象取消引用,则不能取消引用它。

N4058 explains a performance issue with regard to how you have to go about implementing such a thing. N4058解释了一个关于你必须如何实施这样的事情的性能问题。 Since shared_ptr is typically bigger than a single pointer in size, atomic access typically has to be implemented with a spinlock.由于shared_ptr通常大于单个指针的大小,因此原子访问通常必须使用自旋锁来实现。 So either every shared_ptr instance has a spinlock even if it never gets used atomically, or the implementation of those atomic functions has to have a lookaside table of spinlocks for individual objects.因此,要么每个shared_ptr实例都有一个自旋锁,即使它从未被原子使用,要么这些原子函数的实现必须有一个单独对象的自旋锁后备表。 Or use a global spinlock.或者使用全局自旋锁。

None of these are problems if you have a type dedicated to being atomic.如果你有一个专用于原子的类型,这些都不是问题。

atomic<shared_ptr> implementations can use the usual techniques for atomic<T> when T is too large to fit into a CPU atomic operation.T太大而无法适应 CPU 原子操作时, atomic<shared_ptr>实现可以使用atomic<T>的常用技术。 They get to get around the TriviallyCopyable restriction by fiat: the standard requires that they exist and be atomic, so the implementation makes it so.他们通过法令绕过 TriviallyCopyable 限制:标准要求它们存在并且是原子的,所以实现就是这样。 C++ implementations don't have to play by the same rules as regular C++ programs. C++ 实现不必遵循与常规 C++ 程序相同的规则。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM