源码分析
lock_guard
源码解析
// class lock_guard
template <class _Mutex>
class _NODISCARD lock_guard { // class with destructor that unlocks a mutex
public:
using mutex_type = _Mutex;
explicit lock_guard(_Mutex& _Mtx) : _MyMutex(_Mtx) { // construct and lock
_MyMutex.lock();
}
lock_guard(_Mutex& _Mtx, adopt_lock_t) : _MyMutex(_Mtx) {} // construct but don't lock
~lock_guard() noexcept {
_MyMutex.unlock();
}
lock_guard(const lock_guard&) = delete;
lock_guard& operator=(const lock_guard&) = delete;
private:
_Mutex& _MyMutex;
};
lock_guard
,即一个简单的锁RAII对象,在创建时获得锁,析构时释放锁,并没有其他功能。
特性
- 不支持任何形式的复制
- 支持
adopt_lock_t
,不实际加锁,只是获取锁 - 不支持
timed_mutex
中的try_lock,try_lock_for,try_lock_until
```cpp // LOCK PROPERTIES struct adopt_lock_t { // indicates adopt lock explicit adopt_lock_t() = default; };unique_lock
源码解析
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
// CONSTRUCT, ASSIGN, AND DESTROY
unique_lock() noexcept : _Pmtx(nullptr), _Owns(false) {}
_NODISCARD_CTOR explicit unique_lock(_Mutex& _Mtx)
: _Pmtx(_STD addressof(_Mtx)), _Owns(false) { // construct and lock
_Pmtx->lock();
_Owns = true;
}
_NODISCARD_CTOR unique_lock(_Mutex& _Mtx, adopt_lock_t)
: _Pmtx(_STD addressof(_Mtx)), _Owns(true) {} // construct and assume already locked
unique_lock(_Mutex& _Mtx, defer_lock_t) noexcept
: _Pmtx(_STD addressof(_Mtx)), _Owns(false) {} // construct but don't lock
_NODISCARD_CTOR unique_lock(_Mutex& _Mtx, try_to_lock_t)
: _Pmtx(_STD addressof(_Mtx)), _Owns(_Pmtx->try_lock()) {} // construct and try to lock
template <class _Rep, class _Period>
_NODISCARD_CTOR unique_lock(_Mutex& _Mtx, const chrono::duration<_Rep, _Period>& _Rel_time)
: _Pmtx(_STD addressof(_Mtx)), _Owns(_Pmtx->try_lock_for(_Rel_time)) {} // construct and lock with timeout
template <class _Clock, class _Duration>
_NODISCARD_CTOR unique_lock(_Mutex& _Mtx, const chrono::time_point<_Clock, _Duration>& _Abs_time)
: _Pmtx(_STD addressof(_Mtx)), _Owns(_Pmtx->try_lock_until(_Abs_time)) {
// 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>:创建对象并获取锁,在到达某个时间点后释放
特性
- 有5种创建锁的方式
- 支持移动拷贝(拷贝构造和拷贝赋值)
- 支持
timed_lock
中所有的操作,并可转调用 - 支持
swap
(此处为浅交换)