(38)类 _Atomic_lock_guard《T》 ,顾名思义,该类是为了防止使用了自旋锁后,忘记释放自旋锁:
template <class _Spinlock_t> // 锁的保卫,以防止忘记释放锁
class _Atomic_lock_guard
{
private:
_Spinlock_t& _Spinlock; // 数据成员是对自旋锁的左值引用
public:
explicit _Atomic_lock_guard(_Spinlock_t& _Spinlock_) noexcept // 有参构造函数
: _Spinlock(_Spinlock_)
{
_Atomic_lock_acquire(_Spinlock); // 直到获得此自旋锁,构造函数才返回
}
_Atomic_lock_guard(const _Atomic_lock_guard&) = delete; // 禁止 copy 构造函数
_Atomic_lock_guard& operator=(const _Atomic_lock_guard&) = delete; // 禁止 copy 赋值运算符函数
~_Atomic_lock_guard() { _Atomic_lock_release(_Spinlock); } // 析构函数,释放自旋锁
};
(39) 重要基类 _Atomic_storage<T , unsigned long long >,先通过下面的简化代码,显示本模板类的作用。为 atomic《T》 类存储数据。所以阅读 atomic 前需要阅读本类来了解 atomic 里的数据成员是怎么被存储与管理的:
template <class _Ty> // 对齐sizeof (T);x86堆栈在4字节边界上对齐8字节对象
struct _Atomic_padded
{ alignas(sizeof(_Ty)) mutable _Ty _Value; };
template <class _Ty>
struct _Atomic_storage_types {
using _TStorage = _Atomic_padded<_Ty>;
using _Spinlock = long;
};
template <class _Ty>
struct _Atomic_storage_types<_Ty&> {
using _TStorage = _Ty&;
using _Spinlock = _Smtx_t*; // POINTER TO mutex
};
//-----------------------------------------------------------------------------
template <class _Ty, size_t >
struct _Atomic_storage // 分析此版本得了
{ _Ty _Storage{}; };
template <class _Ty>
struct _Atomic_storage<_Ty, 1> // 还有 2 4 8 16 的重载
{ typename _Atomic_storage_types<_Ty>::_TStorage _Storage; };
template <class _Ty, size_t = sizeof(_Ty)> // 还有 1 2 4 8 的重载,但其泛化版本无定义
struct _Atomic_integral : _Atomic_storage<_Ty> {};
template <class _Ty> // 本模板作为普通整形 atomic<int> 的父类 ,本类并无数据成员
struct _Atomic_integral_facade : _Atomic_integral<_Ty>{ };
template <class _Ty> // atomic value
struct atomic : _Choose_atomic_base_t<_Ty>{};
++ 也给出其图片版,看哪个易于阅读:
(40)接着给出该类的成员函数的测试,以了解这些成员函数的功能:
++ 以及:
(41)接着给出该类的源代码:
template <class _Ty, size_t = sizeof(remove_reference_t<_Ty>)> // 模板类的前向声明,下面要用
struct _Atomic_storage;
template <class _Ty, size_t > // 第二个普通模板参数是有默认值的
struct _Atomic_storage // 非类型模板参数,必须在编译时是已知的常量表达式
{
private:
// 简单情况下 _Spinlock = long 类型。引用情况下 _Spinlock 是 void * 类型。
mutable typename _Atomic_storage_types<_Ty>::_Spinlock _Spinlock{}; // 定义了一个自旋锁
protected: // 此函是为了初始化 _Ty 是引用类型的情况,调用的函数的定义在本文最上面
void _Init_spinlock_for_ref() { _Spinlock = __std_atomic_get_mutex(_STD addressof(_Storage)); }
public:
_Ty _Storage{}; // 原子量要保护的数据成员,是个引用,也可以是一个值,都包括了
using _TVal = remove_reference_t<_Ty>;
using _Guard = _Atomic_lock_guard<typename _Atomic_storage_types<_Ty>::_Spinlock>; //锁的 guard
_Atomic_storage() = default; // 默认构造函数
_Atomic_storage(conditional_t<is_reference_v<_Ty>, _Ty, const _TVal> _Value) // 有参构造函数
: _Storage(_Value) { }
void notify_one() { __std_atomic_notify_one_indirect(_STD addressof(_Storage)); } // 搭配 wait(..) 使用
void notify_all() { __std_atomic_notify_all_indirect(_STD addressof(_Storage)); }
void store(const _TVal _Value, const memory_order _Order = memory_order_seq_cst) // 存入值
{
_Check_store_memory_order(_Order); // 允许的写入内存序:relaxed、release、seq_cst
_Guard _Lock{ _Spinlock }; // 先获取自旋锁,再存入数据,这就是原子量的来源
_Storage = _Value;
}
_TVal load(const memory_order _Order = memory_order_seq_cst) const noexcept // 读取值
{
_Check_load_memory_order(_Order); // 允许的读取内存序:relaxed、acquire、seq_cst
_Guard _Lock{ _Spinlock }; // 先获取自旋锁,再读取数据
_TVal _Local(_Storage);
return _Local; // 返回值是值传递
}
_TVal exchange(const _TVal _Value, const memory_order _Order = memory_order_seq_cst) noexcept
{
_Check_memory_order(_Order); // 要求形参是 0~5 中的任意一种内存序即可
_Guard _Lock{ _Spinlock };
_TVal _Result(_Storage);
_Storage = _Value;
return _Result; // 把新值 _Value 存入本模板中,并把保存的旧值返回
}
// 当本类中存储的值 等于形参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;
}
void wait(_TVal _Expected, memory_order = memory_order_seq_cst) const noexcept // 值不等于形参 1 才返回
{
const auto _Storage_ptr = _STD addressof(_Storage );
const auto _Expected_ptr = _STD addressof(_Expected);
for (;;) // wait ()被 nofify ()唤醒后,若原子量的值等于形参 1,还是不会返回的。
{
{ _Guard _Lock{ _Spinlock }; // 取得自旋锁
if (_CSTD memcmp(_Storage_ptr, _Expected_ptr, sizeof(_TVal)) != 0) return;
}
__std_atomic_wait_indirect(_Storage_ptr, _Expected_ptr, sizeof(_TVal), &_Spinlock,
&_Atomic_wait_compare_non_lock_free<decltype(_Spinlock)>, _Atomic_wait_no_timeout);
}
}
};
(42)接着介绍此类的特化版本,具有更高的效率,也省去了该泛型类包含的自旋锁。先对特化版本的一个成员函数进行测试,确定其返回值:
(43)接着介绍该类 _Atomic_storage《T , unsgned long_long 》的特化版本之一: _Atomic_storage《T , 1》。该模板类有对常见数据类型有多个特化版本,接着一一介绍。经仔细查看与测试,所有同名成员函数的语义都没有发生改变:
template <class _Ty> // lock-free using 1-byte intrinsics,无锁,使用 1 字节内置函数
struct _Atomic_storage<_Ty, 1> // 本特化版本,缺少了内置的自旋锁的数据成员,效率更高
{
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>;
_Atomic_storage() = default; // 默认构造函数
// non-atomically initialize this atomic
_Atomic_storage(conditional_t<is_reference_v<_Ty>, _Ty, const _TVal> _Value) // 有参构造函数
: _Storage{_Value} { }
// template <class _Ty, class _Value_type> 本函数会让本线程睡眠等待,直到形参 1 和 2 不等才返回
// void _Atomic_wait_direct 更准确的描述是等待原子量(形参1 ) 发生变化后才返回
// ( _Atomic_storage<_Ty>* this, _Value_type expected_bytes, memory_order order)
// 所以,本成员函数的语义是等待本类的数据成员与形参 1 不等才返回。
void wait(const _TVal _Expected, const memory_order _Order = memory_order_seq_cst)
{
_Atomic_wait_direct(this, _Atomic_reinterpret_as<char>(_Expected), _Order);
}
void notify_one() { __std_atomic_notify_one_direct(_STD addressof(_Storage)); }
void notify_all() { __std_atomic_notify_all_direct(_STD addressof(_Storage)); }
/*
template <class _Integral, class _Ty> // 本函返回形参引用的原始数据的地址
volatile _Integral* _Atomic_address_as(_Ty& _Source) // 本函数是精简版
{ return &reinterpret_cast<volatile _Integral&>(_Source); }
*/
void store(const _TVal _Value) noexcept // store with sequential consistency 函数重载
{
const auto _Mem = _Atomic_address_as<char>(_Storage);
const char _As_bytes = _Atomic_reinterpret_as<char>(_Value);
(void) _InterlockedExchange8(_Mem, _As_bytes);
}
void store(const _TVal _Value, const memory_order _Order) noexcept // store with given memory order
{
const auto _Mem = _Atomic_address_as<char>(_Storage);
const char _As_bytes = _Atomic_reinterpret_as<char>(_Value);
switch (_Order)
{
case memory_order_relaxed:
__iso_volatile_store8(_Mem, _As_bytes); return;
case memory_order_release:
_Compiler_or_memory_barrier(); // _Compiler_or_memory_barrier() = _Compiler_barrier()
__iso_volatile_store8(_Mem, _As_bytes);
return;
default:
case memory_order_consume: // 以下几种内存序违法
case memory_order_acquire:
case memory_order_acq_rel:
_INVALID_MEMORY_ORDER;
// [[fallthrough]];
case memory_order_seq_cst: store(_Value); return;
}
}
//************
_TVal load() const noexcept // load with sequential consistency 函数重载,返回值是值传递
{
const auto _Mem = _Atomic_address_as<char>(_Storage); // 获得本类中数据成员的地址
char _As_bytes = __iso_volatile_load8(_Mem);
_Compiler_or_memory_barrier(); //= _Compiler_barrier() 插入内存栅栏
return reinterpret_cast<_TVal&>(_As_bytes);
}
_TVal load(const memory_order _Order) const noexcept // load with given memory order
{
const auto _Mem = _Atomic_address_as<char>(_Storage);
char _As_bytes = __iso_volatile_load8(_Mem);
_Load_barrier(_Order); // 检查并根据形参内存序的级别,设置内存栅栏
return reinterpret_cast<_TVal&>(_As_bytes);
}
//*************
// exchange with given memory order 按指定内存序,把形参 1 的值存入本类中
_TVal exchange(const _TVal _Value, const memory_order _Order = memory_order_seq_cst)
{
char _As_bytes;
_ATOMIC_CHOOSE_INTRINSIC(_Order, _As_bytes, _InterlockedExchange8, // 由宏函数完成实际的内存交换
_Atomic_address_as<char>(_Storage), _Atomic_reinterpret_as<char>(_Value));
return reinterpret_cast<_TVal&>(_As_bytes); // 经测试,是把本类保存的旧值返回
}
/* 此宏函数的定义在本头文件的最上面
#define _ATOMIC_CHOOSE_INTRINSIC(_Order, _Result, _Intrinsic, ...) \
_Check_memory_order(_Order); \
_Result = _Intrinsic(__VA_ARGS__)
*/
// 当本类中存储的值 等于形参1 时,把形参 2 的值存入本类;
// 当本类中存储的值 不等于形参1 时,把本类中的值写入形参 1 。有点指令 cmpxchg 的语义。
// 返回值表示形参1 与本类中的值是否相等,是则返回 true。
bool compare_exchange_strong // CAS with given memory order
(_TVal& _Expected, const _TVal _Desired, const memory_order _Order = memory_order_seq_cst)
{
char _Expected_bytes = _Atomic_reinterpret_as<char>(_Expected); // 形参 1 是左值引用
char _Prev_bytes; // 下面宏函数里 函_InterlockedCompareExchange8() 的返回值
// 经测试,函 _InterlockedCompareExchange8() 总返回其形参1 的原值。这里则是本类中的数据成员原始值
_ATOMIC_CHOOSE_INTRINSIC(_Order, _Prev_bytes, _InterlockedCompareExchange8, // 包含的函数变了
_Atomic_address_as<char>(_Storage), _Atomic_reinterpret_as<char>(_Desired), _Expected_bytes);
if (_Prev_bytes == _Expected_bytes) return true;
reinterpret_cast<char&>(_Expected) = _Prev_bytes; // 形参1 是左值引用
return false;
}
};
(44)
谢谢