atomic 注释16:特化模板类 _Atomic_storage<_Ty&, 16>,wins 平台系统函数 _InterlockedExchangeAdd8 (),

(47)接着继续学习该类的特化版本 _Atomic_storage<_Ty&, 16>,原子地管理 16 字节的数据。但注意形参 1 是左值引用。先给出一个测试,以确定其中一个成员函数的功能:

在这里插入图片描述

++ 接着给出其源代码

#ifdef _WIN64                    // 本特化版本值存在于 win64 平台上。 
template <class _Ty>             // lock-free using 16-byte intrinsics
struct _Atomic_storage<_Ty&, 16> // 无锁,使用 16 字节内置函数 
{ 
    struct _Int128 {  alignas(16) long long _Low;   long long _High; }; // 类内定义的类

    typename _Atomic_storage_types<_Ty&>::_TStorage _Storage; // 本类的数据成员将是左值引用
/*
template <class _Ty> // 这个特化版本的数据成员的定义,也不同于其泛化版本
struct _Atomic_padded { alignas(sizeof(_Ty)) mutable _Ty _Value;  };

template <class _Ty>
struct _Atomic_storage_types       {  using _TStorage = _Atomic_padded<_Ty>;  };

template <class _Ty>
struct _Atomic_storage_types<_Ty&> {  using _TStorage = _Ty&;  };
*/
    using _TVal = remove_reference_t<_Ty&>;  // 对于左值引用,_TVal 仍然是基础无引用类型

    _Atomic_storage() = default;                                                   // 默认构造函数

    // non-atomically initialize this atomic
    _Atomic_storage(conditional_t<is_reference_v<_Ty&>, _Ty&, const _TVal> _Value) // 有参构造函数 
        : _Storage{_Value} {} 

    // 本函数的语义不变:仍然是本类中的数据成员的值不等于形参1 才返回
    void wait(_TVal _Expected, memory_order _Order = memory_order_seq_cst) const noexcept 
    {
        const auto _Storage_ptr  = _STD addressof(_Storage) ;
        const auto _Expected_ptr = _STD addressof(_Expected);

        _Int128 _Expected_bytes = reinterpret_cast<const _Int128&>(_Expected);

        for (;;)
        {
            const _TVal _Observed = load(_Order);

            _Int128 _Observed_bytes = reinterpret_cast<const _Int128&>(_Observed);

            if (_Observed_bytes._Low != _Expected_bytes._Low || _Observed_bytes._High != _Expected_bytes._High) 
                return;

            __std_atomic_wait_indirect(_Storage_ptr, _Expected_ptr, sizeof(_TVal), nullptr,
                &_Atomic_wait_compare_16_bytes, _Atomic_wait_no_timeout);
        }
    }

    void notify_one() { __std_atomic_notify_one_indirect(_STD addressof(_Storage)); }

    void notify_all() { __std_atomic_notify_all_indirect(_STD addressof(_Storage)); }

    //**********************

    // 本函数的语义不同于 8 字节以下版本的语义。 本函没有比较的功能,只做交换。
    // 本函中形参1 与 2 的值是相同的。
    // 本函的功能就是把形参 1 的值设置为本类的数据成员,并把本类中原来的值由形参 1 带回。
    // 本函对 16 字节交换成功返回 true , 失败返回 false 。
    bool compare_exchange_strong  // CAS with given memory order 本函数被下面的成员函数调用
    (_TVal& _Expected, const _TVal _Desired, const memory_order _Order = memory_order_seq_cst)
    {
        _Int128 _Desired_bytes{}; // 从上下文看,此函数的形参1 与 2 是相等的。
        _CSTD memcpy(&_Desired_bytes, _STD addressof(_Desired), sizeof(_TVal));

        _Int128 _Expected_temp{};
        _CSTD memcpy(&_Expected_temp, _STD addressof(_Expected), sizeof(_TVal));

        unsigned char _Result;     (void)_Order;

//宏函数 _STD_COMPARE_EXCHANGE_128 = __std_atomic_compare_exchange_128,在本文件上面
//结合上下猜测,函 __std_atomic_compare_exchange_128(..) 的返回值表 16 字节的原子交换操作是否成功;
//交换成功返回 true = 1 , 失败未交换返回 false = 0 
//该函数是把其形参1 中的值与形参4 中的值进行原子交换。形参 2与 3 表示形参4 中的值。
        _Result = _STD_COMPARE_EXCHANGE_128 ( &reinterpret_cast<long long&>(_Storage),
                       _Desired_bytes._High, _Desired_bytes._Low, &_Expected_temp._Low);

        if (_Result == 0) // 因为 16 字节的原子交换失败,恢复形参 1 里的值
            _CSTD memcpy(_STD addressof(_Expected), &_Expected_temp, sizeof(_TVal));

        return _Result != 0;
    }

    _TVal exchange(const _TVal _Value) noexcept // exchange with sequential consistency 函数重载
    {
        _TVal _Result{ _Value };

        while ( !compare_exchange_strong(_Result, _Value) ) {}// keep trying

        return _Result;
    }

    _TVal exchange(const _TVal _Value, const memory_order _Order) noexcept // exchange with given memory order
    {
        _TVal _Result{ _Value };

        while (!compare_exchange_strong(_Result, _Value, _Order)) {} // keep trying

        return _Result;
    }

    //***********************

    // store with sequential consistency
    void store(const _TVal _Value) noexcept {   (void) exchange(_Value);   } // 函数重载

    void store(const _TVal _Value, const memory_order _Order) noexcept // store with given memory order
    { 
        _Check_store_memory_order(_Order);
        (void) exchange(_Value, _Order);
    }

    //*********************

    _TVal load() const noexcept  // load with sequential consistency
    { 
        long long* const _Storage_ptr = // 把 16 字节结构体的地址作为 long long 类型的地址
            const_cast<long long*>(_Atomic_address_as<const long long>(_Storage));

        _Int128 _Result{}; // atomic CAS 0 with 0

        //此函数交换形参 1 与 4 中的值, 形参2与3表示形参 4 中的值。交换成功返回 true。
        (void) _STD_COMPARE_EXCHANGE_128(_Storage_ptr, 0, 0, &_Result._Low);

        return reinterpret_cast<_TVal&>(_Result);
    }
/*
template <class _Integral, class _Ty> // 本函返回形参引用的原始数据的地址
volatile _Integral* _Atomic_address_as(_Ty& _Source)  // 本函数是精简版
{   return &reinterpret_cast<volatile _Integral&>(_Source);   }
*/
    _TVal load(const memory_order _Order) const noexcept // load with given memory order
    { 
        _Check_load_memory_order(_Order);
        return load();

    }

};
#endif // _WIN64

(48)上面介绍的 _Atomic_storage《 T,size_t 》 系列,是存储了一个数据,并完成了原子性的读取和赋值该数据。接下来,介绍该类的子类 _Atomic_integral《 T, size_t 》 系列,又增加了新的成员函数,以支持对整数的原子操作,原子性的完成整数运算。先介绍其中被调用的一个 windows 平台的系统函数,是这些操作系统的内部函数的支持,才完成了 STL 库的 atomic 类的多线程中的运算定义。

在这里插入图片描述

++ 以下是一个简单的示例,展示了如何使用 _InterlockedExchangeAdd8 来安全地增加一个全局计数器的值

#include <windows.h>
#include <stdio.h>

#pragma intrinsic(_InterlockedExchangeAdd8)

volatile BYTE counter = 0;   // 该全局量被 volatile 修饰

DWORD WINAPI ThreadFunc(LPVOID lpParam) 
{
    for (int i = 0; i < 1000; ++i) {  // 原子地增加计数器的值
        SHORT oldValue = _InterlockedExchangeAdd8((volatile BYTE*)&counter, 1);
        // 这里可以添加一些代码来处理 oldValue,但在这个例子中我们仅仅增加计数器
    }
    return 0;
}

int main() {
    HANDLE hThreads[2];                                              // 建立了两个线程来同时增加全局量的值。
    hThreads[0] = CreateThread(NULL, 0, ThreadFunc, NULL, 0, NULL);
    hThreads[1] = CreateThread(NULL, 0, ThreadFunc, NULL, 0, NULL);

    WaitForMultipleObjects(2, hThreads, TRUE, INFINITE);

    // 输出最终计数器的值
    printf("Final counter value: %d\n", counter);

    return 0;
}

在这里插入图片描述

(49)

谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值