GCC原子shared_ptr实现

2023-12-02

根据https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57250,GCC 4.9已经支持原子shared_ptr运营。

使用 GCC 4.9.2,我能够编译一个使用原子的程序shared_ptr. The -mcx16标志是必需的,因为 x86_64 上的 GCC 实现显然需要cmpxchg16b,这是有道理的,因为我假设对 a 进行原子操作shared_ptr需要同时原子地更新指针本身和引用计数。

然而,当我尝试实际use原子的shared_ptr库,它的行为不符合我的预期。所以,要么我没有正确使用它,要么 GCC 实现有缺陷。大多数时候,我有 99% 的信心认为我只是做错了,但由于这是一个相对较新的功能,而且行为看起来很奇怪,所以我只有大约 50% 的信心认为这是我的错案件。

这是一个创建原子的简单程序shared_ptr,然后对shared_ptr执行一系列并发读取和写入:

void test()
{
        std::atomic<std::shared_ptr<int>> p(std::shared_ptr<int>(new int(10)));

        std::cout << "Use count : " << p.load().use_count() << std::endl;
        std::cout << "Initial value of p : " << *(p.load()) << std::endl;

        std::vector<std::thread> threads;
        const std::size_t num_threads = 8;

        for (std::size_t i = 0; i != num_threads; ++i)
        {
                threads.emplace_back([&p, i](){

                        std::shared_ptr<int> x = p.load();
                        while (!p.compare_exchange_weak(
                                x,
                                std::shared_ptr<int>(new int(i + 5))
                        )) ;
                });
        }

        for (auto& t : threads) t.join();

        std::cout << "Use count : " << p.load().use_count() << std::endl;
        std::cout << "Final value of p : " << *(p.load()) << std::endl;
}

当我编译并运行时,输出是:

~$ g++ test2.cpp -o test2 -std=c++11 -lpthread -mcx16
~$ ./test2
Use count : 1
Initial value of p : 0
Use count : 0
Final value of p : 0

但这个输出对我来说没有意义。首先,初始化原子后shared_ptr到一个值10,当我加载它并读取初始值(在生成任何线程之前)时,我得到一个0。其次,所有线程加入后,该值仍然是0,即使没有线程可能将其设置为0。最奇怪的是,在线程加入之后,use_count()的shared_ptr是0!然而原子shared_ptr对象仍在范围内,因此使用计数应该是1.

我很确定 GCC 实现在这里有缺陷,但是根据我上面发布的链接,GCC 4.9 有一个完整的原子shared_ptr实施,以及...

~$ gcc --version
~$ gcc (Debian 4.9.2-10) 4.9.2

那么...到底发生了什么?我想得到某种确认,要么这里的 GCC 4.9.2 实现有缺陷或不完整,要么我对如何使用原子完全错误/困惑shared_ptr.


"atomic shared_ptr操作”是指免费std::atomic_(store|load|exchange|compare_exchange_strong|compare_exchange_weak)(_explicit)?函数模板用于shared_ptr,记录在案here。 GCC 直到 5 才拥有它们。(有趣的事实:它的实现实际上在幕后使用了 16 个互斥体的全局数组。)

实例化std::atomic over std::shared_ptr导致未定义的行为,如std::atomic需要一个可简单复制的类型。

并发TS有std::experimental::atomic_shared_ptr.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GCC原子shared_ptr实现 的相关文章

随机推荐

  • OpenCV imwrite 函数导致“未定义符号”

    我正在开发一个软件 它由一些带有 python 绑定的核心 C 代码组成 C 代码已经使用了大量 OpenCV 但现在我试图在两者之间保存图像 但我似乎无法使用imwrite功能 将其添加到 main cpp 中并使用 默认 构建在 ecl
  • 如何使用表单名称作为字符串创建新的表单实例

    使用表单名称创建封闭表单的新表单实例的代码 我想用变量替换长的选择案例列表 模块完整代码 在 Access 2010 中 我有一个 VBA 函数 当给定包含表单名称的字符串时 该函数会打开表单的新实例 通过将表单变量 frm 添加到集合中
  • 图片在浏览器中显示为垃圾字符

    谁能告诉我为什么当我尝试通过浏览器访问图像 URL 时 它显示一堆内容类型为文本 纯文本的垃圾字符 eg https www domainname com client image name jpg显示如下 3 1AQa q2 B R b3
  • 如何使用 php 将文件添加到 ziparchive 中新创建的文件夹中?

    如上图所示 我有组织在虚拟文件夹中的图像 在 mysql 数据库中 但不是真实文件夹中 我需要使所选文件夹可供使用下载为 zip 文件 我能够压缩图像 但是我们如何添加子目录以便向其中添加图像 我尝试使用addEmptyDir 但无法找到向
  • 当条码扫描仪发送以换行符结尾的数据时如何使按钮散焦

    我正在编写一个 C 条形码应用程序 我有一个 EAN 13 正则表达式来检测 Form1 KeyPress 函数中的条形码 我没有机制来检测输入来自哪里 这是我的问题 我的表单中有一个重置按钮 可以清除 dataGridView 中列出的所
  • 无法全局安装旧版本的 phpunit phar

    正如给出的https phpunit de manual current en installation html installation phar verification 全局安装PHAR的步骤是 wget https phar ph
  • DLIB:针对 194 个地标训练 Shape_predictor(helen 数据集)

    我正在训练DLIB s 形状预测器对于 194 个面部特征点 使用海伦数据集用于通过以下方式检测人脸特征点face landmark detection ex cppdlib 库 现在它给了我一个sp dat大约的二进制文件45 MB与给定
  • Live Sass 编译器 - @use 导致编译错误

    我在用着Live Sass 编译器 v3 0 0在我的 VS Code 中 每当我使用 use rule从另一个文件导入变量 但是 当我使用 Sass 命令行界面时 sass watch 编译我的文件 它会抛出没有错误 因此 我想问一下这是
  • macOS DriverKit:制作 PCI dext 来替换内置驱动程序

    我正在尝试在 DriverKit 中编写一个用户空间 PCI 驱动程序 用于教育 研究目的 我找到了一个来自 WorthDoingBadly 的示例其中包含 PCI 设备 dext 的样板代码 我已删除了漏洞利用代码 我已将其修改为通过以下
  • 检测 IE 中包含 PDF 的 iFrame 的 onload 事件

    我发现这个问题已经在这里被问过很多次了 有些解决方案部分有效 这就是场景 我需要加载一个包含 pdf 的 iframe 有可能找不到 PDF 我将在 iFrame 中显示错误页面 加载 iframe 后 我会查找标签使用 iframe co
  • 我如何在不使用 virtual 关键字的情况下重写这个 C++ 继承的成员函数?

    我有一个小程序来演示简单的继承 我正在定义一个派生自哺乳动物的 Dog 类 这两个类共享一个名为 ToString 的简单成员函数 当我不使用 virtual 关键字时 Dog 如何覆盖 Mammal 类中的实现 我是否需要使用 virtu
  • Android:修改录制的视频质量

    我正在使用 MediaRecorder 录制视频 假设视频的大小保持不变 我不清楚应该使用哪些参数来改变图像的质量 例如 我想始终创建 640x480 mp4 视频 我可以调整哪些参数来提高或降低质量 您可以尝试使用 recorder se
  • 自 ubuntu 升级以来未定义对“dlopen”的引用

    自从我升级到 ubuntu 13 10 和 gcc 4 8 1 以来 我遇到了对 dlopen 问题的未定义引用 makefile 已经工作多年了 特定的调用是 gcc rdynamic o ov dbutil ov dbutil o li
  • 离子闪屏和旋转器

    有没有办法在启动屏幕中自定义微调器 目前我正在使用 cordova flashscreen 插件 我想更改出现在启动屏幕上的微调器的颜色 In platforms android src org apache cordova splashs
  • 将sql查询转换为jpa

    我有一个疑问 SELECT d name count e id FROM department d LEFT OUTER JOIN employee e on e department id d id and e salary gt 500
  • 如何从 PInvoke 本机回调返回 StringBuilder 或其他字符串缓冲区

    我想要一种干净的方法来增加本机代码填充所需的 StringBuilder 的大小 下面的回调方法看起来很干净 但不知何故我们得到了缓冲区的副本而不是实际的缓冲区 我感兴趣解释和解决方案 最好坚持回调类型分配 因为如果它可以工作的话 它会很好
  • 将 MBF 双精度转换为 IEEE

    我在下面找到了一个将 MBF 转换为 IEEE 的主题 将 MBF Single 和 Double 转换为 IEEE 谁能解释一下下面标记的代码的功能是什么 暗淡符号 As Byte mbf 6 和 ToByte H80 AND H80 是
  • 根据给定的坐标移动鼠标

    我想要的是 在记录鼠标移动并保存坐标 索引 位置后 我必须加载鼠标坐标并使鼠标根据加载的坐标移动 我没有代码可以给你看 因为我现在陷入困境 private void button3 Click 1 object sender EventAr
  • Linux 相当于 Windows DLL 转发器或 MacOS reexport_library

    我有一个共享库 试图提供一个标准化的接口 基本上是一个函数列表 其中一些功能已由另一个共享库提供 因此 我可以编写附加函数并要求用户链接到这两个库 即让他这样做 g foo c lmine lother 但是 为了让用户更轻松 我不想这样做
  • GCC原子shared_ptr实现

    根据https gcc gnu org bugzilla show bug cgi id 57250 GCC 4 9已经支持原子shared ptr运营 使用 GCC 4 9 2 我能够编译一个使用原子的程序shared ptr The m