atomic 注释30:类 atomic_ref<T>的成员函数 compare_exchange_strong () 及 compare_exchange_weak ()及该模板类的源代码

(84)测试这俩成员函数

在这里插入图片描述

(85) atomic_ref《T》 专注于保护已经存在的变量。该类的数据成员是对已存在变量的左值引用。而 atomic 的数据成员则是 atomic 中独有的,与别的变量没有联系。这俩模板类适用于不同的场景。前者的源码,在 c++20 规范里,大师们才给出了定义。

#if _HAS_CXX20
// template <class _TVal, class _Ty = _TVal>   // 此处是为了区分浮点型与其它类型(整数、指针等)
// using _Choose_atomic_base_t = typename _Select<is_floating_point_v<_TVal>> ::
//                template _Apply<_Atomic_floating<_Ty>, _Choose_atomic_base2_t<_TVal, _Ty>>;
// 经测试, atomic<T> 中 T 不可以为左值引用或右值引用类型,所以 c++20 里定义了本模板类 
// template <class _Ty> 
// struct atomic : _Choose_atomic_base_t<_Ty> {} ;
template <class _Ty>                                  // 使用时定义模板参数 _Ty 为基础非引用类型即可。 
struct atomic_ref : _Choose_atomic_base_t<_Ty, _Ty&>  // atomic reference 本模板类专注于引用的原子存储
{ 
public:  // 以下是类里定义的静态变量
    // template <size_t _TypeSize> // 能同时满足这些条件的只有上面的 1 2 4 8 这四个数。此时不用内部自旋锁了。
    // bool _Is_always_lock_free = _TypeSize <= 8 && (_TypeSize & (_TypeSize - 1)) == 0;
    static constexpr bool is_always_lock_free = _Is_always_lock_free<sizeof(_Ty)>;

    static constexpr bool _Is_potentially_lock_free = // 64 位环境里 16 字节也认为是可免自旋锁的。
        sizeof(_Ty) <= 2 * sizeof(void*) && (sizeof(_Ty) & (sizeof(_Ty) - 1)) == 0;

    static constexpr size_t required_alignment = _Is_potentially_lock_free ? sizeof(_Ty) : alignof(_Ty);
    // 经测试 sizeof(T) >= alignof(T)

private:
    // #define  _ATOMIC_REF_CHECK_ALIGNMENT(cond, mesg)  _STL_VERIFY(cond, mesg)  宏函数
    // [[maybe_unused]] 是 c++17 引入的对变量、参数、函数的修饰符,不要提示变量未使用。
    // 本函数的语义是要求本原子量引用的基础变量的内存地址是对齐的。否则报错。
    static void _Check_alignment ( [[maybe_unused]] const _Ty& _Value ) // 本函被构造函数调用
    {   
        _ATOMIC_REF_CHECK_ALIGNMENT(    // 要求形参1  cond 必须为 true
            ( reinterpret_cast<uintptr_t>( _STD addressof(_Value)) & (required_alignment - 1) ) == 0,
            "atomic_ref underlying object is not aligned as required_alignment"
                                     ); // uintptr_t = u_long_long
    }

    using _Base = _Choose_atomic_base_t<_Ty, _Ty&>;

public: // 经测试,模板参数 _Ty 只可以是基础类型。若 _Ty 是左值引用或右值引用则报错。 
    static_assert(is_trivially_copyable_v<_Ty>, "atomic_ref<T> requires T to be trivially copyable.");

    using value_type = _Ty; // 值类型,不包括引用 & && 这俩修饰符

    explicit atomic_ref(_Ty& _Value) : _Base(_Value)   // 有参构造函数
    {
        if constexpr (_Is_potentially_lock_free) // 免自旋锁的情况下要求变量的地址是内存对齐的。
            _Check_alignment(_Value);
        else   
            this->_Init_spinlock_for_ref();  // 否则就初始化基类中的自旋锁 _Atomic_storage<T>::_Spinlock
    }
/*
template <class _Ty, size_t = sizeof(remove_reference_t<_Ty>)> 
struct _Atomic_storage 
{
    mutable typename _Atomic_storage_types<_Ty>::_Spinlock _Spinlock{}; // 定义了一个自旋锁

    void _Init_spinlock_for_ref() { _Spinlock = __std_atomic_get_mutex(_STD addressof(_Storage)); }
};
*/
    atomic_ref(const atomic_ref&) noexcept = default;  // 禁止 copy 构造函数

    atomic_ref& operator=(const atomic_ref&) = delete; // 禁止 copy 赋值运算符函数

    bool is_lock_free()  // 测试模板参数 _Ty 是否是免自旋锁的。
    {
        if constexpr (is_always_lock_free) // 64 位 intel CPU 是有汇编指令 cmpxchg16b 的。
            return true;
        else 
            return __std_atomic_has_cmpxchg16b() != 0; // 有汇编指令 cmpxchg16b 则也是免自旋锁的。
    }

    //****写入原子量****

    void store(const _Ty _Value) const noexcept 
    {
        const_cast<atomic_ref*>(this)->_Base::store(_Value);
    }

    void store(const _Ty _Value, const memory_order _Order) const noexcept 
    {
        const_cast<atomic_ref*>(this)->_Base::store(_Value, _Order);
    }

    _Ty operator=(const _Ty _Value) const noexcept 
    {
        store(_Value);
        return _Value;
    }

    //****写入原子量,返回旧值****

    _Ty exchange(const _Ty _Value) const noexcept 
    {
        return const_cast<atomic_ref*>(this)->_Base::exchange(_Value);
    }

    _Ty exchange(const _Ty _Value, const memory_order _Order) const noexcept 
    {
        return const_cast<atomic_ref*>(this)->_Base::exchange(_Value, _Order);
    }

    //**** 类型转换运算符与唤醒 ****

    operator _Ty () const noexcept {   return this->load();   }

    void notify_one() const noexcept 
    {
        const_cast<atomic_ref*>(this)->_Base::notify_one();
    }

    void notify_all() const noexcept 
    {
        const_cast<atomic_ref*>(this)->_Base::notify_all();
    }

    //****比较及强交换****

    bool compare_exchange_strong(_Ty& _Expected, const _Ty _Desired) const noexcept 
    {
        return const_cast<atomic_ref*>(this)->_Base::compare_exchange_strong(_Expected, _Desired);
    }
/*
template <class _Ty, size_t = sizeof(remove_reference_t<_Ty>)>
struct _Atomic_storage
{
    // 当本类中存储的值   等于形参1 时,把形参 2 的值存入本类;
    // 当本类中存储的值 不等于形参1 时,把本类中的值写入形参 1 。有点指令 cmpxchg 的语义。
    // 返回值表示形参1 与本类中的值是否相等,是则返回 true。
    bool compare_exchange_strong  // 注意:形参1 是左值引用,对左值引用取地址返回的是原始值的地址
    (_TVal& _Expected, const _TVal _Desired, const memory_order _Order = memory_order_seq_cst)
    {
        _Check_memory_order(_Order);
        const auto _Storage_ptr = _STD addressof(_Storage); // 取本类中数据成员的地址
        const auto _Expected_ptr = _STD addressof(_Expected);
        bool _Result;

        _Guard _Lock{ _Spinlock };         // 取得自旋锁

        _Result = _CSTD memcmp(_Storage_ptr, _Expected_ptr, sizeof(_TVal)) == 0;

        if (_Result)
            _CSTD memcpy(_Storage_ptr, _STD addressof(_Desired), sizeof(_TVal));
        else
            _CSTD memcpy(_Expected_ptr, _Storage_ptr, sizeof(_TVal));

        return _Result;
    }

};
*/
    bool compare_exchange_strong(_Ty& _Expected, const _Ty _Desired, const memory_order _Order) const noexcept 
    {
        return const_cast<atomic_ref*>(this)->_Base::compare_exchange_strong(_Expected, _Desired, _Order);
    }

    bool compare_exchange_strong( _Ty& _Expected, const _Ty _Desired, 
        const memory_order _Success, const memory_order _Failure) const noexcept
    {
        return compare_exchange_strong(_Expected, _Desired, _Combine_cas_memory_orders(_Success, _Failure));
    }

    //****比较及弱交换****

    bool compare_exchange_weak(_Ty& _Expected, const _Ty _Desired) const noexcept
    {
        return compare_exchange_strong(_Expected, _Desired);
    }

    bool compare_exchange_weak(_Ty& _Expected, const _Ty _Desired, const memory_order _Order) const noexcept
    {
        return compare_exchange_strong(_Expected, _Desired, _Order);
    }

    bool compare_exchange_weak( _Ty& _Expected, const _Ty _Desired, const memory_order _Success, 
        const memory_order _Failure) const noexcept
    {
        return compare_exchange_strong(_Expected, _Desired, _Combine_cas_memory_orders(_Success, _Failure));
    }

};
#endif // _HAS_CXX20

(86)

谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值