visual-c++ - 如何用原子操作实现 std::weak_ptr::lock?

标签 visual-c++ libstdc++ libc++ stdatomic weak-ptr

最近想用C实现原子引用计数器,所以引用了STL中std::shared_ptr的实现,对weak_ptr::lock的实现很困惑。 执行compared_and_exchange时,clang指定了memory_order_seq_cst,g++指定了memory_order_acq_rel,MSVC指定了memory_order_relaxed。 我认为 memory_order_relaxed 已经足够了,因为如果 user_count 不为零,则不需要同步任何数据。 我不是这方面的专家,谁能提供一些建议?

以下是代码片段:

MSVC

    bool _Incref_nz() noexcept { // increment use count if not zero, return true if successful
        auto& _Volatile_uses = reinterpret_cast<volatile long&>(_Uses);
#ifdef _M_CEE_PURE
        long _Count = *_Atomic_address_as<const long>(&_Volatile_uses);
#else
        long _Count = __iso_volatile_load32(reinterpret_cast<volatile int*>(&_Volatile_uses));
#endif
        while (_Count != 0) {
            const long _Old_value = _INTRIN_RELAXED(_InterlockedCompareExchange)(&_Volatile_uses, _Count + 1, _Count);
            if (_Old_value == _Count) {
                return true;
            }

            _Count = _Old_value;
        }

        return false;
    }

clang/libcxx

__shared_weak_count*
__shared_weak_count::lock() noexcept
{
    long object_owners = __libcpp_atomic_load(&__shared_owners_);
    while (object_owners != -1)
    {
        if (__libcpp_atomic_compare_exchange(&__shared_owners_,
                                             &object_owners,
                                             object_owners+1))
            return this;
    }
    return nullptr;
}

gcc/libstdc++

 template<>
    inline bool
    _Sp_counted_base<_S_atomic>::
    _M_add_ref_lock_nothrow() noexcept
    {
      // Perform lock-free add-if-not-zero operation.
      _Atomic_word __count = _M_get_use_count();
      do
    {
      if (__count == 0)
        return false;
      // Replace the current counter value with the old value + 1, as
      // long as it's not changed meanwhile.
    }
      while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
                      true, __ATOMIC_ACQ_REL,
                      __ATOMIC_RELAXED));
      return true;
    }

最佳答案

我正在尝试自己回答这个问题。

standard spec只说 weak_ptr::lock 应该作为原子操作执行,但没有更多关于内存顺序的信息。这样不同的线程就可以直接并行调用 weak_ptr::lock 而不会出现任何竞争条件,当这种情况发生时,不同的实现会提供不同的 memory_order。 但无论如何,以上所有的实现都是正确的。

关于visual-c++ - 如何用原子操作实现 std::weak_ptr::lock?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70331658/

相关文章:

c++ - 我是否误解了这个默认参数 shared_ptr 的范围?

c++ - Clang 的 libc++:在 std::chrono::duration 的定义中使用 long long

c++ - rapidxml 在 wchar_t 内容上抛出异常

c# - 如何在 C# .net 中获取处理器 CPU 标志?

c++ - 我该如何修复 MSVC 2005 错误 : unresolved external symbol __environ

php - shell_exec 命令找不到库

c++ - 为什么 C++ 可执行文件在与较新的 libstdc++.so 链接时运行速度如此之快?

c++ - libc++ 的 std::is_literal_type 是如何工作的?

c++ - 在 Clang 和 libc++ 中使用反向 vector 迭代器时,“重载运算符的使用不明确”

c++ - 是否存在 C4930 Visual C++ 警告未指示错误的真实案例?