(34) 基类 _Mutex_base、子类 mutex、recursive_mutex 及类 lock_guard 的源码,接着开始分小段来介绍本 头文件的源代码,因为本头文件中的类、模板类太多,知识点太多。先介绍的是互斥量的基类以及互斥量的定义。由此也知道了互斥量的成员函数以及其功能:
class _Mutex_base // base class for all mutex types 所有互斥类型的基类
{
private:
friend condition_variable;
friend condition_variable_any;
char _Mtx_storage[80]; //这是一个简化定义,参考了内存对齐与数据量需求等方面
// using _Mtx_t = struct _Mtx_internal_imp_t *; 返回值是一个指针
_Mtx_t _Mymtx() { return reinterpret_cast<_Mtx_t>(&_Mtx_storage); }
public:
// enum { _Mtx_plain=0x01, _Mtx_try=0x02, _Mtx_timed=0x04, _Mtx_recursive=0x100 };
// mutex : _Mutex_base { mutex() : _Mutex_base( ) {} };
// recursive_mutex : _Mutex_base { recursive_mutex() : _Mutex_base( _Mtx_recursive ) {} };
_Mutex_base(int _Flags = 0) noexcept // 默认的父类构造函数
{ // 可见,所有 mutex 互斥量默认具有 2_Mtx_try 标志
_Mtx_init_in_situ(_Mymtx(), _Flags | _Mtx_try); // 底层函数使用了 pthread 库的实现为例
} // int pthread_mutex_init ( pthread_mutex_t * mutex , pthread_mutexattr_t * attr);
// int pthread_mutex_destroy ( pthread_mutex_t * mutex );
~_Mutex_base() { _Mtx_destroy_in_situ( _Mymtx() ); } // 析构函数,调用了底层的销毁互斥量的函数
_Mutex_base(const _Mutex_base&) = delete; // 禁止 copy 构造函数
_Mutex_base& operator=(const _Mutex_base&) = delete; // 禁止 copy 赋值运算符函数
// 当函 _Mtx_lock(...) 返 _Thrd_success 时才不报错
// int pthread_mutex_lock ( pthread_mutex_t * mutex ) ;
void lock() { _Check_C_return( _Mtx_lock( _Mymtx() ) ); }
// 函 _Mtx_unlock( _Mtx_t ) 总返回 _Thrd_success
// int pthread_mutex_unlock ( pthread_mutex_t * mutex ) ;
void unlock() { _Mtx_unlock( _Mymtx() ); }
// enum { _Thrd_success, _Thrd_nomem, _Thrd_timedout, _Thrd_busy, _Thrd_error };
bool try_lock()
{ // int __cdecl _Mtx_trylock( _Mtx_t );
const auto _Res = _Mtx_trylock( _Mymtx() );
switch (_Res) { // 只可以加锁成功或忙碌,否则报错终止进程。
case _Thrd_success: return true;
case _Thrd_busy : return false;
default : _Throw_C_error( _Res ); // 报错,终止进程
}
}
using native_handle_type = void* ; // void* __cdecl _Mtx_getconcrtcs( _Mtx_t );
native_handle_type native_handle() { return _Mtx_getconcrtcs( _Mymtx() ); }
};
// mutex 与其父类 _Mutex_base 一模一样,没有做任何功能上的增加删除
class mutex : public _Mutex_base
{
public:
mutex() : _Mutex_base() {}
mutex(const mutex&) = delete; // 禁止了 copy 构造与 copy 赋值运算符函数
mutex& operator=(const mutex&) = delete;
};
// class for recursive mutual exclusion 递归互斥的类,
class recursive_mutex : public _Mutex_base // 从源代码看,未对基类 _Mutex_base 做任何功能扩展
{ // 可在同一个线程里对一个锁多次加锁
public:
recursive_mutex() : _Mutex_base(_Mtx_recursive) {}
recursive_mutex(const recursive_mutex&) = delete; // 禁止了 copy 构造与 copy 赋值运算符函数
recursive_mutex& operator=(const recursive_mutex&) = delete;
bool try_lock() noexcept { return _Mutex_base::try_lock(); }
};
template <class _Mutex>
class lock_guard // class with destructor that unlocks a mutex
{
private:
_Mutex& _MyMutex;
public:
using mutex_type = _Mutex;
// construct and lock 在创建本 lock_guard 类型变量的时候,直接给上锁
explicit lock_guard(_Mutex& _Mtx) : _MyMutex(_Mtx) { _MyMutex.lock(); }
// 构造函数的重载
lock_guard(_Mutex& _Mtx, adopt_lock_t) : _MyMutex(_Mtx) {} // construct but don't lock
~lock_guard() { _MyMutex.unlock(); } // 出了本类型变量的作用域,析构函数中自动解锁
lock_guard(const lock_guard&) = delete; // 禁止的 copy 构造与 copy 赋值运算符函数
lock_guard& operator=(const lock_guard&) = delete;
};
(35)构成重载的标志类,有些类只有定义,只有类名字,但没有任何功能。这样的类有什么作用呢? 其实就是为了构成函数重载,或者模板特化,其仅仅起到一个标志作用。参数的数量不同,顺序不同,类型不同,就构成了函数的重载:
++ 以上这些类,构成了 unique_lock 的构造函数的重载。
(36) unique_lock 的源码,其功能,类似于 lcok_guard,或者智能指针,来管理互斥量,以免线程结束时忘记对 mutex 解锁:
// _Mutex 可以是 mutex 或 timed_mutex , 但不可以是递归锁。本模板禁止重复加锁。
// whizzy class with destructor that unlocks mutex 具有解锁 Mutex 的析构函数的奇特类
template <class _Mutex>
class unique_lock
{
private:
_Mutex* _Pmtx; // 数据成员是一个互斥量的地址,类似智能指针
bool _Owns; // 互斥量是否已被上锁,这是个 布尔量
void _Validate() const // check if the mutex can be locked测试是否可以加锁
{
if (!_Pmtx) // 本 unique_lock 没有管理到锁
_Throw_system_error(errc::operation_not_permitted);
if (_Owns) // 若互斥量已被上锁,则报错
_Throw_system_error(errc::resource_deadlock_would_occur);
}
public:
using mutex_type = _Mutex;
unique_lock() noexcept : _Pmtx(nullptr), _Owns(false) {} // 默认的无参构造函数
explicit unique_lock(_Mutex& _Mtx) : // 有参构造函数 construct and lock
_Pmtx(_STD addressof(_Mtx)), _Owns(false)
{
_Pmtx->lock();
_Owns = true;
}
~unique_lock() noexcept { if (_Owns) _Pmtx->unlock(); } // 析构函数
// construct and assume already locked 有参构造函数
unique_lock(_Mutex& _Mtx, adopt_lock_t) : _Pmtx(_STD addressof(_Mtx)), _Owns(true) {}
// construct but don't lock 有参构造函数
unique_lock(_Mutex& _Mtx, defer_lock_t) : _Pmtx(_STD addressof(_Mtx)), _Owns(false) {}
// construct and try to lock 有参构造函数,尝试加一次锁
unique_lock(_Mutex& _Mtx, try_to_lock_t): _Pmtx(_STD addressof(_Mtx)), _Owns(_Pmtx->try_lock()) {}
/*
class _Mutex_base // base class for all mutex types 所有互斥类型的基类
{
aligned_storage_t<_Mtx_internal_imp_size, _Mtx_internal_imp_alignment> _Mtx_storage;
bool try_lock() // enum { _Thrd_success, _Thrd_nomem, _Thrd_timedout, _Thrd_busy, _Thrd_error };
{
// int __cdecl _Mtx_trylock(_Mtx_t);
const auto _Res = _Mtx_trylock(_Mymtx());
switch (_Res)
{
case _Thrd_success: return true;
case _Thrd_busy: return false;
default: _Throw_C_error(_Res);
}
}
};
*/
unique_lock(const unique_lock&) = delete; // 禁止了 copy 构造函数
unique_lock& operator=(const unique_lock&) = delete; // 禁止了 copy 赋值运算符函数
unique_lock(unique_lock&& _Other) noexcept // 移动构造函数
: _Pmtx(_Other._Pmtx), _Owns(_Other._Owns)
{
_Other._Pmtx = nullptr;
_Other._Owns = false;
}
unique_lock& operator=(unique_lock&& _Other) // 移动赋值运算符函数
{
if (this != _STD addressof(_Other))
{ // 若本 unique_lock 管理的互斥量已被上锁,先解锁
if (_Owns) _Pmtx->unlock();
_Pmtx = _Other._Pmtx;
_Owns = _Other._Owns;
_Other._Pmtx = nullptr;
_Other._Owns = false;
}
return *this;
}
// 当互斥量存在且未被锁定,函 _Validate() 才不会报错
// 对本 unique_lock 管理的互斥量, 上锁
void lock () { _Validate(); _Pmtx->lock(); _Owns = true; }
// 对本 unique_lock 管理的互斥量, try 尝试上锁
bool try_lock() { _Validate(); _Owns = _Pmtx->try_lock(); return _Owns; }
void unlock()
{
if (!_Pmtx || !_Owns) // 若不存在互斥量,或存在但未被锁定,报错
_Throw_system_error(errc::operation_not_permitted);
_Pmtx->unlock();
_Owns = false;
}
void swap(unique_lock& _Other) noexcept
{
_STD swap(_Pmtx, _Other._Pmtx);
_STD swap(_Owns, _Other._Owns);
}
_Mutex* mutex() const noexcept { return _Pmtx; }
_Mutex* release() noexcept // 返回互斥量的裸指针,但未释放锁
{ // release ,释放,不再管理此互斥量
_Mutex* _Res = _Pmtx;
_Pmtx = nullptr;
_Owns = false;
return _Res;
}
bool owns_lock() const { return _Owns; } // 若互斥量已被加锁,则返回 true
explicit operator bool() const { return _Owns; } // 类型转换运算符,返回是否上了锁
// 模板参数 _Mutex 须是 timed_mutex 或 recursive_timed_mutex 类型。带时间的构造函数
unique_lock(_Mutex& _Mtx, const xtime* _Abs_time) : _Pmtx(_STD addressof(_Mtx)), _Owns(false)
{
_Owns = _Pmtx->try_lock_until(_Abs_time); // try to lock until _Abs_time
}
template <class _Clock, class _Duration> // 有参构造函数,形参是 time_point 类型
unique_lock(_Mutex& _Mtx, const chrono::time_point<_Clock, _Duration>& _Abs_time)
: _Pmtx(_STD addressof(_Mtx)), _Owns(_Pmtx->try_lock_until(_Abs_time))
{
#if _HAS_CXX20
static_assert(chrono::is_clock_v<_Clock>, "Clock type required");
#endif // _HAS_CXX20
}
template <class _Rep, class _Period> // construct and lock with timeout
unique_lock(_Mutex& _Mtx, const chrono::duration<_Rep, _Period>& _Rel_time) // 形参是时间段
: _Pmtx(_STD addressof(_Mtx)), _Owns(_Pmtx->try_lock_for(_Rel_time)) {}
bool try_lock_until(const xtime* _Abs_time) // 限时加锁的成员函数
{
_Validate();
_Owns = _Pmtx->try_lock_until(_Abs_time);
return _Owns;
}
template <class _Clock, class _Duration>
bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time)
{
#if _HAS_CXX20
static_assert(chrono::is_clock_v<_Clock>, "Clock type required");
#endif // _HAS_CXX20
_Validate();
_Owns = _Pmtx->try_lock_until(_Abs_time);
return _Owns;
}
// 核心是调用被 unique_lock 封装的 _Mutex . try_lock_for()
template <class _Rep, class _Period>
bool try_lock_for(const chrono::duration<_Rep, _Period>& _Rel_time)
{
_Validate();
_Owns = _Pmtx->try_lock_for(_Rel_time);
return _Owns;
}
};
++ 解释为什么 unique_lock 不能管理互斥锁 :
(37)
谢谢