<mutex>注释 7:基类 _Mutex_base、子类 mutex、recursive_mutex 及类 lock_guard 的源码,构成重载的标志类,unique_lock<T> 的源码

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

谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangzhangkeji

谢谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值