(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)
谢谢