源码分析

lock_guard源码解析

  1. // class lock_guard
  2. template <class _Mutex>
  3. class _NODISCARD lock_guard { // class with destructor that unlocks a mutex
  4. public:
  5. using mutex_type = _Mutex;
  6. explicit lock_guard(_Mutex& _Mtx) : _MyMutex(_Mtx) { // construct and lock
  7. _MyMutex.lock();
  8. }
  9. lock_guard(_Mutex& _Mtx, adopt_lock_t) : _MyMutex(_Mtx) {} // construct but don't lock
  10. ~lock_guard() noexcept {
  11. _MyMutex.unlock();
  12. }
  13. lock_guard(const lock_guard&) = delete;
  14. lock_guard& operator=(const lock_guard&) = delete;
  15. private:
  16. _Mutex& _MyMutex;
  17. };

lock_guard,即一个简单的锁RAII对象,在创建时获得锁,析构时释放锁,并没有其他功能。

特性

  1. 不支持任何形式的复制
  2. 支持adopt_lock_t,不实际加锁,只是获取锁
  3. 不支持timed_mutex中的try_lock,try_lock_for,try_lock_until

    unique_lock源码解析

    ```cpp // LOCK PROPERTIES struct adopt_lock_t { // indicates adopt lock explicit adopt_lock_t() = default; };

struct defer_lock_t { // indicates defer lock explicit defer_lock_t() = default; };

struct try_to_lock_t { // indicates try to lock explicit try_to_lock_t() = default; };

_INLINE_VAR constexpr adopt_lock_t adopt_lock{}; _INLINE_VAR constexpr defer_lock_t defer_lock{}; _INLINE_VAR constexpr try_to_lock_t try_to_lock{};

// CLASS TEMPLATE unique_lock template class unique_lock { // whizzy class with destructor that unlocks mutex public: using mutex_type = _Mutex;

  1. // CONSTRUCT, ASSIGN, AND DESTROY
  2. unique_lock() noexcept : _Pmtx(nullptr), _Owns(false) {}
  3. _NODISCARD_CTOR explicit unique_lock(_Mutex& _Mtx)
  4. : _Pmtx(_STD addressof(_Mtx)), _Owns(false) { // construct and lock
  5. _Pmtx->lock();
  6. _Owns = true;
  7. }
  8. _NODISCARD_CTOR unique_lock(_Mutex& _Mtx, adopt_lock_t)
  9. : _Pmtx(_STD addressof(_Mtx)), _Owns(true) {} // construct and assume already locked
  10. unique_lock(_Mutex& _Mtx, defer_lock_t) noexcept
  11. : _Pmtx(_STD addressof(_Mtx)), _Owns(false) {} // construct but don't lock
  12. _NODISCARD_CTOR unique_lock(_Mutex& _Mtx, try_to_lock_t)
  13. : _Pmtx(_STD addressof(_Mtx)), _Owns(_Pmtx->try_lock()) {} // construct and try to lock
  14. template <class _Rep, class _Period>
  15. _NODISCARD_CTOR unique_lock(_Mutex& _Mtx, const chrono::duration<_Rep, _Period>& _Rel_time)
  16. : _Pmtx(_STD addressof(_Mtx)), _Owns(_Pmtx->try_lock_for(_Rel_time)) {} // construct and lock with timeout
  17. template <class _Clock, class _Duration>
  18. _NODISCARD_CTOR unique_lock(_Mutex& _Mtx, const chrono::time_point<_Clock, _Duration>& _Abs_time)
  19. : _Pmtx(_STD addressof(_Mtx)), _Owns(_Pmtx->try_lock_until(_Abs_time)) {
  20. // construct and lock with timeout

if _HAS_CXX20

    static_assert(chrono::is_clock_v<_Clock>, "Clock type required");

endif // _HAS_CXX20

}

_NODISCARD_CTOR unique_lock(_Mutex& _Mtx, const xtime* _Abs_time)
    : _Pmtx(_STD addressof(_Mtx)), _Owns(false) { // try to lock until _Abs_time
    _Owns = _Pmtx->try_lock_until(_Abs_time);
}

_NODISCARD_CTOR 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)) {
        if (_Owns) {
            _Pmtx->unlock();
        }

        _Pmtx        = _Other._Pmtx;
        _Owns        = _Other._Owns;
        _Other._Pmtx = nullptr;
        _Other._Owns = false;
    }
    return *this;
}

~unique_lock() noexcept {
    if (_Owns) {
        _Pmtx->unlock();
    }
}

unique_lock(const unique_lock&) = delete;
unique_lock& operator=(const unique_lock&) = delete;

void lock() { // lock the mutex
    _Validate();
    _Pmtx->lock();
    _Owns = true;
}

_NODISCARD bool try_lock() {
    _Validate();
    _Owns = _Pmtx->try_lock();
    return _Owns;
}

template <class _Rep, class _Period>
_NODISCARD bool try_lock_for(const chrono::duration<_Rep, _Period>& _Rel_time) {
    _Validate();
    _Owns = _Pmtx->try_lock_for(_Rel_time);
    return _Owns;
}

template <class _Clock, class _Duration>
_NODISCARD 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;
}

_NODISCARD bool try_lock_until(const xtime* _Abs_time) {
    _Validate();
    _Owns = _Pmtx->try_lock_until(_Abs_time);
    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* release() noexcept {
    _Mutex* _Res = _Pmtx;
    _Pmtx        = nullptr;
    _Owns        = false;
    return _Res;
}

_NODISCARD bool owns_lock() const noexcept {
    return _Owns;
}

explicit operator bool() const noexcept {
    return _Owns;
}

_NODISCARD _Mutex* mutex() const noexcept {
    return _Pmtx;
}

private: _Mutex* _Pmtx; bool _Owns;

void _Validate() const { // check if the mutex can be locked
    if (!_Pmtx) {
        _Throw_system_error(errc::operation_not_permitted);
    }

    if (_Owns) {
        _Throw_system_error(errc::resource_deadlock_would_occur);
    }
}

}; ```

功能分析

std::unique_lock,维护两个变量

  • _Mutex* _Pmtx :指向锁的指针 【lock_guard为引用】
  • bool _Owns :维护加锁的状态

unique_lock有 操作锁的方式,均在创建时获取:

  • 默认模式:创建并获取锁
  • adopt_lock_t: 创建对象,并假设已获取锁【此处创建对象时并不加锁】
  • defer_lock_t: 创建对象,但创建时不加锁
  • try_to_lock_t: 创建对象,并尝试加锁。【try_lock(),成功时返回true】
  • chrono::duration<_Rep, _Period>: 创建对象并获取锁,在一段时间后释放
  • chrono::time_point<_Clock, _Duration>:创建对象并获取锁,在到达某个时间点后释放

    特性

  1. 有5种创建锁的方式
  2. 支持移动拷贝(拷贝构造和拷贝赋值)
  3. 支持timed_lock中所有的操作,并可转调用
  4. 支持swap(此处为浅交换)