有没有办法在 libstdc++ 中创建原子 shared_ptr?
Is there a way of making atomic shared_ptr in libstd++?
我需要在我的代码中使用原子 shared_ptr - 我有单 reader 多编写器场景,其中一个小数据结构将被多个线程复制和覆盖。
在看到 this and this(和我自己的测试)后,自由原子函数似乎在 GCC 4.9.2 中仍然不起作用。
我试过简单地将 shared_ptr 放入 atomic:
#include <atomic>
#include <iostream>
#include <memory>
std::atomic<std::shared_ptr<std::string> > a_var;
void place() {
std::shared_ptr<std::string> ptr1(new std::string("abc"));
a_var.store(ptr1);
}
int main(int argc, const char *argv[]) {
place();
std::shared_ptr<std::string> ptr2 = a_var.load();
std::cout<< *ptr2 << std::endl;
return 0;
}
但是在使用 g++ --std=c++11 -g <filename> -latomic
编译后它会抛出段错误。
似乎正在发生的事情是在调用 store
之后使用复制构造函数创建了一个新的 shared_ptr
,但是它立即被删除并且在退出 place
之后 ptr1 被释放,所以*ptr2
抛出。
关于如何让它发挥作用的任何想法
暂时忘掉 C++11 闪亮的玩具,看看你真正想要实现的目标。
这里要保护的是你的数据结构,而不是引用它的指针。
我假设 "free atomic function" 你的意思是无锁。编译器不允许您随意使用原子是有充分理由的。这是因为在除极少数情况外的所有情况下,这都比使用普通的旧阻塞同步效率低。
C++11 使玩原子变量成为时尚的最新奇想,但尽管这些东西被包裹在一层漂亮的语法糖中,但它非常危险,并且会导致不稳定的 and/or 低效设计除了经验丰富的专家以外的任何人都在使用。
在 C++14 中,您将拥有 atomic_shared_pointer
,它需要自定义代码,当然不能仅通过将共享指针包装到原子模板中来使其工作,但无论如何这会也没有解决你的问题。
std::atomic<.>
只能与 'trivially copyable type'.
一起使用
std::shared_ptr<std::string>
显然不满足这些条件。某处 atomic
会将对象复制为内存块并违反 类.
中的一个或多个不变量
比如我们都知道:
std::shared_ptr<std::string> s(new std::string("abc"));
std::shared_ptr<std::string> t;
memcpy(&t,&s,sizeof(std::shared_ptr<std::string>));
到副本末尾都是可编译和可执行的。这也是灾难的保证。
在您的情况下 ptr1
没有 "know" 它已被复制,因此当它 (ptr1
) 超出范围时它会删除该字符串。然后你访问字符串。 繁荣。游戏结束。
实现您正在做的事情的标准方法是用 std::mutex
保护 share_ptr
。没有简单的方法来提供指向字符串的无锁指针。这样的对象将引发计算革命。
我需要在我的代码中使用原子 shared_ptr - 我有单 reader 多编写器场景,其中一个小数据结构将被多个线程复制和覆盖。
在看到 this and this(和我自己的测试)后,自由原子函数似乎在 GCC 4.9.2 中仍然不起作用。
我试过简单地将 shared_ptr 放入 atomic:
#include <atomic>
#include <iostream>
#include <memory>
std::atomic<std::shared_ptr<std::string> > a_var;
void place() {
std::shared_ptr<std::string> ptr1(new std::string("abc"));
a_var.store(ptr1);
}
int main(int argc, const char *argv[]) {
place();
std::shared_ptr<std::string> ptr2 = a_var.load();
std::cout<< *ptr2 << std::endl;
return 0;
}
但是在使用 g++ --std=c++11 -g <filename> -latomic
编译后它会抛出段错误。
似乎正在发生的事情是在调用 store
之后使用复制构造函数创建了一个新的 shared_ptr
,但是它立即被删除并且在退出 place
之后 ptr1 被释放,所以*ptr2
抛出。
关于如何让它发挥作用的任何想法
暂时忘掉 C++11 闪亮的玩具,看看你真正想要实现的目标。
这里要保护的是你的数据结构,而不是引用它的指针。
我假设 "free atomic function" 你的意思是无锁。编译器不允许您随意使用原子是有充分理由的。这是因为在除极少数情况外的所有情况下,这都比使用普通的旧阻塞同步效率低。
C++11 使玩原子变量成为时尚的最新奇想,但尽管这些东西被包裹在一层漂亮的语法糖中,但它非常危险,并且会导致不稳定的 and/or 低效设计除了经验丰富的专家以外的任何人都在使用。
在 C++14 中,您将拥有 atomic_shared_pointer
,它需要自定义代码,当然不能仅通过将共享指针包装到原子模板中来使其工作,但无论如何这会也没有解决你的问题。
std::atomic<.>
只能与 'trivially copyable type'.
std::shared_ptr<std::string>
显然不满足这些条件。某处 atomic
会将对象复制为内存块并违反 类.
比如我们都知道:
std::shared_ptr<std::string> s(new std::string("abc"));
std::shared_ptr<std::string> t;
memcpy(&t,&s,sizeof(std::shared_ptr<std::string>));
到副本末尾都是可编译和可执行的。这也是灾难的保证。
在您的情况下 ptr1
没有 "know" 它已被复制,因此当它 (ptr1
) 超出范围时它会删除该字符串。然后你访问字符串。 繁荣。游戏结束。
实现您正在做的事情的标准方法是用 std::mutex
保护 share_ptr
。没有简单的方法来提供指向字符串的无锁指针。这样的对象将引发计算革命。