【问题标题】:How is std::atomic<T>::operator= implemented for immutable types?std::atomic<T>::operator= 如何为不可变类型实现?
【发布时间】:2020-08-31 14:21:05
【问题描述】:

我了解到线程之间进行通信的一种方法是共享一些原子数据结构。例如:

struct Point {
    int const x, y;
};

std::atomic<Point> some_point_in_shared_memory{Point{0, 0}};

尽管Point::operator=(Point const &amp;)被删除,但似乎有no problem调用std::atomic&lt;Point&gt;的赋值运算符如下:

some_point_in_shared_memory = Point{1, 2};

这个操作如何实现?

我可能想到的一个解决方案是使用placement new 在旧对象之上构造一个新对象,但显然是it is not exception safe。还是因为Point 可以轻松复制所以没关系?

【问题讨论】:

  • 您能否详细说明“似乎没有问题”?你的代码编译了吗?如果是这样,您的标准库有一个错误,因为 std::atomic&lt;T&gt; 要求 T 可以轻松复制
  • gcc 和 clang 接受这个。 MSVC 和 ICC 没有。
  • @alterigel 见this。还将链接编辑为没问题。此外,Point 可以轻松复制。
  • 你在哪里删除Point::operator=(Point const &amp;)?您将Point 声明为普通结构,因此它看起来不像minimal reproducible example。此外,您的标题仍然显示“不可变”。真的是你的意思吗?
  • 此外,在启用优化的情况下进行编译,以将 asm 输出简化为预期的 qword seq-cst 存储,使用 xchg 实现其隐含的 lock 行为。 godbolt.org/z/sdTEv9

标签: c++ thread-safety stdatomic exception-safety


【解决方案1】:

来自cppreference

主 std::atomic 模板可以用任何 TriviallyCopyable 类型 T 同时满足 CopyConstructible 和 可复制。如果以下任何值,则程序是非良构的 是假的:

std::is_trivially_copyable<T>::value
std::is_copy_constructible<T>::value
std::is_move_constructible<T>::value
std::is_copy_assignable<T>::value
std::is_move_assignable<T>::value

您的 T 不是 CopyAssignable,而这一行

some_point_in_shared_memory = Point{1, 2};

格式不正确。应该有编译器错误。不幸的是,我没有让 GCC 发出错误或警告(-pedantic -Wpedantic -pedantic-errors -Wall -Werror=pedantic 无效)。

【讨论】:

  • 我们确实需要概念
  • @BennyK 我不明白你在说什么。如果Point 是不可变的,那么您很可能不需要std::atomic&lt;Point&gt;,因为Point 已经只能读取不能写入
猜你喜欢
  • 2022-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-22
  • 1970-01-01
  • 2012-08-03
  • 1970-01-01
  • 2012-02-18
相关资源
最近更新 更多