命名空间
变体
操作

std::atomic<std::shared_ptr>

来自 cppreference.com
< cpp‎ | memory‎ | shared ptr
 
 
工具库
语言支持
类型支持 (基本类型,RTTI)
库特性测试宏 (C++20)
动态内存管理
程序工具
协程支持 (C++20)
可变参数函数
调试支持
(C++26)
三路比较
(C++20)
(C++20)(C++20)(C++20)
(C++20)(C++20)(C++20)
通用工具
日期和时间
函数对象
格式化库 (C++20)
(C++11)
关系运算符 (在 C++20 中已弃用)
整数比较函数
(C++20)(C++20)(C++20)   
(C++20)
交换类型操作
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
通用词汇类型
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)
基本字符串转换
(C++17)
(C++17)

 
动态内存管理
未初始化内存算法
受限未初始化内存算法
分配器
垃圾收集支持
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)



 
 
定义在头文件 <memory>
template< class T >
struct std::atomic<std::shared_ptr<T>>;
(自 C++20 起)

std::atomic 的部分模板特化,针对 std::shared_ptr<T>,允许用户以原子方式操作 shared_ptr 对象。

如果多个执行线程访问同一个 std::shared_ptr 对象,而没有进行同步,并且其中任何访问使用了 shared_ptr 的非常量成员函数,那么就会发生数据竞争,除非所有这些访问都通过 std::atomic<std::shared_ptr> 的实例进行(或者,从 C++20 开始已弃用,通过 独立函数std::shared_ptr 进行原子访问)。

关联的 use_count 增加保证是原子操作的一部分。关联的 use_count 减少在原子操作之后进行,但不要求是原子操作的一部分,除非是当在失败的 CAS 中覆盖 expecteduse_count 发生改变。任何关联的删除和释放都在原子更新步骤之后进行,并且不是原子操作的一部分。

请注意,shared_ptr 的控制块是线程安全的:不同的非原子 std::shared_ptr 对象可以使用可变操作(例如 operator=reset)由多个线程同时访问,即使这些实例是副本,并在内部共享相同的控制块。

类型 T 可以是不完整类型。

内容

[edit] 成员类型

成员类型 定义
value_type std::shared_ptr<T>

[edit] 成员函数

所有非特化的 std::atomic 函数也由此特化提供,并且没有其他成员函数。

atomic<shared_ptr<T>>::atomic

constexpr atomic() noexcept = default;
(1)
constexpr atomic( std::nullptr_t ) noexcept : atomic() {}
(2)
atomic( std::shared_ptr<T> desired ) noexcept;
(3)
atomic( const atomic& ) = delete;
(4)
1,2) 初始化底层的 shared_ptr<T> 为空值。
3) 初始化底层的 shared_ptr<T>desired 的副本。与任何 std::atomic 类型一样,初始化不是原子操作。
4) 原子类型不可复制/移动构造。

atomic<shared_ptr<T>>::operator=

void operator=( const atomic& ) = delete;
(1)
void operator=( std::shared_ptr<T> desired ) noexcept;
(2)
void operator=( std::nullptr_t ) noexcept;
(3)
1) 原子类型不可复制/移动赋值。
2) 值赋值,等同于 store(desired)
3) 将原子共享指针重置为空指针值。等同于 store(nullptr);

atomic<shared_ptr<T>>::is_lock_free

bool is_lock_free() const noexcept;

如果此类型的对象的所有原子操作都是无锁的,则返回 true,否则返回 false

atomic<shared_ptr<T>>::store

void store( std::shared_ptr<T> desired,
            std::memory_order order = std::memory_order_seq_cst ) noexcept;

原子地将 *this 的值替换为 desired 的值,就像通过 p.swap(desired) 一样,其中 p 是底层的 std::shared_ptr<T>。内存根据 order 排序。如果 orderstd::memory_order_consumestd::memory_order_acquirestd::memory_order_acq_rel,则行为未定义。

atomic<shared_ptr<T>>::load

原子地返回底层共享指针的副本。内存根据 order 排序。如果 orderstd::memory_order_releasestd::memory_order_acq_rel,则行为未定义。

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

operator std::shared_ptr<T>() const noexcept;

等同于 return load();

atomic<shared_ptr<T>>::exchange

std::shared_ptr<T> exchange( std::shared_ptr<T> desired,
                             std::memory_order order = std::memory_order_seq_cst ) noexcept;

原子地将底层的 std::shared_ptr<T> 替换为 desired,就像通过 p.swap(desired) 一样,其中 p 是底层的 std::shared_ptr<T>,并返回 p 在交换之前立即具有的值的副本。内存根据 order 排序。这是一个原子读-修改-写操作。

atomic<shared_ptr<T>>::compare_exchange_weak, compare_exchange_strong

bool compare_exchange_strong( std::shared_ptr<T>& expected, std::shared_ptr<T> desired,
                              std::memory_order success, std::memory_order failure ) noexcept;
(1)
bool compare_exchange_weak( std::shared_ptr<T>& expected, std::shared_ptr<T> desired,
                            std::memory_order success, std::memory_order failure ) noexcept;
(2)
bool compare_exchange_strong( std::shared_ptr<T>& expected, std::shared_ptr<T> desired,
                              std::memory_order order = std::memory_order_seq_cst ) noexcept;
(3)
bool compare_exchange_weak( std::shared_ptr<T>& expected, std::shared_ptr<T> desired,
                            std::memory_order order = std::memory_order_seq_cst ) noexcept;
(4)
1) 如果底层 std::shared_ptr<T> 存储与 expected 相同的 T* 并与其共享所有权,或者底层和 expected 都为空,则从 desired 赋值到底层 std::shared_ptr<T>,返回 true,并根据 success 顺序执行内存操作;否则,从底层 std::shared_ptr<T> 赋值到 expected,返回 false,并根据 failure 顺序执行内存操作。如果 failurestd::memory_order_releasestd::memory_order_acq_rel,则行为未定义。成功时,操作是对 *this 的原子读-修改-写操作,并且在原子更新后不会访问 expected。失败时,操作是对 *this 的原子加载操作,并且 expected 会使用从原子对象读取的现有值进行更新。对 expecteduse_count 的更新是此原子操作的一部分,尽管写入本身(以及任何后续的释放/销毁)并不需要是原子操作。
2)(1) 相同,但可能也发生虚假失败。
3) 等效于:return compare_exchange_strong(expected, desired, order, fail_order);,其中 fail_orderorder 相同,但 std::memory_order_acq_rel 被替换为 std::memory_order_acquirestd::memory_order_release 被替换为 std::memory_order_relaxed
4) 等效于:return compare_exchange_weak(expected, desired, order, fail_order);,其中 fail_orderorder 相同,但 std::memory_order_acq_rel 被替换为 std::memory_order_acquirestd::memory_order_release 被替换为 std::memory_order_relaxed

atomic<shared_ptr<T>>::wait

void wait( std::shared_ptr<T> old,
           std::memory_order order = std::memory_order_seq_cst ) const noexcept;

执行原子等待操作。

load(order)old 进行比较,如果它们等效,则阻塞直到 *thisnotify_one()notify_all() 通知。重复此过程,直到 load(order) 发生变化。此函数保证只有在值发生变化时才会返回,即使底层实现发生虚假解除阻塞也是如此。

内存操作根据 order 顺序执行。如果 orderstd::memory_order_releasestd::memory_order_acq_rel,则行为未定义。

注意:如果两个 shared_ptr 存储相同的指针,并且它们要么共享所有权,要么都为空,则它们等效。

atomic<shared_ptr<T>>::notify_one

void notify_one() noexcept;

执行原子通知操作。

如果有一个线程在 *this 上的原子等待操作(即 wait())中被阻塞,则解除阻塞至少一个这样的线程;否则不执行任何操作。

atomic<shared_ptr<T>>::notify_all

void notify_all() noexcept;

执行原子通知操作。

解除阻塞所有在 *this 上的原子等待操作(即 wait())中被阻塞的线程,如果有的话;否则不执行任何操作。

[edit] 成员常量

此特化也提供唯一的标准 std::atomic 成员常量 is_always_lock_free

atomic<shared_ptr<T>>::is_always_lock_free

static constexpr bool is_always_lock_free = /*implementation-defined*/;

[edit] 注意

特性测试 Std 特性
__cpp_lib_atomic_shared_ptr 201711L (C++20) std::atomic<std::shared_ptr>

[edit] 示例

[edit] 缺陷报告

以下行为变更缺陷报告被追溯应用于之前发布的 C++ 标准。

DR 应用于 发布的行为 正确的行为
LWG 3661 C++20 atomic<shared_ptr<T>> 不能从 nullptr 进行常量初始化 可以常量初始化
LWG 3893 C++20 LWG3661 使得 atomic<shared_ptr<T>> 不能从 nullptr_t 赋值 恢复可赋值性

[edit] 另请参阅

(C++11)
用于 bool、整型、 浮点型、(自 C++20 起) 和指针类型的原子类模板及其特化
(类模板) [edit]