【问题标题】:Why does libc++'s implementation of shared_ptr use full memory barriers instead of relaxed?为什么 libc++ 的 shared_ptr 实现使用完整的内存屏障而不是放松的?
【发布时间】:2015-03-27 18:19:49
【问题描述】:

在boost 的shared_ptr 实现中,它使用relaxed memory ordering to increment its reference count。这看起来很安全,因为减量使用获取/释放来确保在释放内存之前线程可以看到任何先前的减量。这个方法似乎是正确的,出现在 Herb Sutters talk on atomics

在 libc++ 的实现中使用full memory barriers

template <class T>
inline T
increment(T& t) _NOEXCEPT
{
    return __sync_add_and_fetch(&t, 1);
}

template <class T>
inline T
decrement(T& t) _NOEXCEPT
{
    return __sync_add_and_fetch(&t, -1);
}

}  // name

这个决定有什么理由吗?它们之间是否有任何性能或安全差异?

【问题讨论】:

  • 根据implementation details here,它说“为了满足线程安全要求,引用计数器通常使用等效于 std::atomic::fetch_add 和 std::memory_order_relaxed 来递增和递减。”我希望找到它的来源以确认该声明,但我无法找到 gcc 的 libc++ 源代码的在线文档(尽管它们只是天真的 Google 搜索,也许有人可以提供链接)。我注意到您的链接是针对 LLVM 的。
  • 谁编写了该代码,何时,为什么以及他们还编写了什么......如果有办法找出来。 ;)
  • @Aggieboy 我认为我链接的镜像也是 GCC 上 libc++ 的源代码,您只需使用 -gcc-toolchain 编译它。 libstd++(GCC 上的默认标准库)使用__gnu_cxx::__exchange_and_add,我相信这也是一个完整的障碍,但我不确定。似乎应该以宽松的障碍来实现它是常识,但我似乎找不到除了 boost 之外的任何库
  • @UlrichEckhardt 我会满足于一些像样的 cmets :P。我只是好奇为什么任何 STL 实现都会违背线程安全引用计数的最佳实践(为了性能),因为它显然有能力使用它(原子在那里,只需使用它们!)。也许他们就是这样做的,但也许更熟悉原子的人可以阐明这样做是否有充分的理由
  • 为了不留下任何不好的感觉,@ChrisT,我想(讽刺地)建议你检查相应的版本控制系统。这就是在许多此类系统中可以使用“责备”或“注释”命令的原因。我不确定这个讽刺是否发生过......

标签: c++ boost thread-safety shared-ptr libc++


【解决方案1】:

因为当我编写该代码时,编译器 (clang) 尚未实现 C++11 原子。我再也没有回来清理它。

这里没有什么微妙之处。 :-)

【讨论】:

  • 最后,一个我理解的与原子有关的答案!
  • 哈,当这个答案被显示为“审核”我的评论时,我刚刚得到一个“你没有通过”......我已将其标记为垃圾邮件,认为有人没有代表(它没有显示真正的用户)极不可能编写代码,更不用说整个库了,其他人现在正在询问:-D
  • 乍一看,我认为这是一个糟糕的自我回答(尤其是笑脸)。我对审计保持警惕,所以我通过了,但这不是一个很好的审计选择。
  • 对于此页面的未来访问者,似乎已修复此问题:llvm.org/bugs/show_bug.cgi?id=22803
猜你喜欢
  • 1970-01-01
  • 2016-02-18
  • 1970-01-01
  • 2015-02-22
  • 1970-01-01
  • 2011-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多