首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用原子操作实现std::weak_ptr::lock?

如何使用原子操作实现std::weak_ptr::lock?
EN

Stack Overflow用户
提问于 2021-12-13 08:19:00
回答 1查看 163关注 0票数 3

最近我尝试用C实现一个原子引用计数器,所以我提到了std::shared_ptr在STL中的实现,我对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

代码语言:javascript
复制
    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

代码语言:javascript
复制
__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++

代码语言:javascript
复制
 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;
    }
EN

回答 1

Stack Overflow用户

发布于 2021-12-14 08:57:23

我正试图亲自回答这个问题。

标准规格只说weak_ptr::lock应该作为原子操作来执行,但是没有更多关于内存顺序的内容。这样不同的线程可以在没有任何竞争条件的情况下直接并行地调用weak_ptr::lock,当发生这种情况时,不同的实现提供了不同的memory_order。但无论如何,上述所有实现都是正确的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70331658

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档