(45) 本头文件的全部源码 ,很长,作为前面的汇总,共 1100 行:
// mutex standard header
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#pragma once
#ifndef _MUTEX_
#define _MUTEX_
#include <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR
#ifdef _M_CEE_PURE
#error <mutex> is not supported when compiling with /clr:pure.
#endif // _M_CEE_PURE
// 以上说明定义了宏 _M_CEE_PURE 就报错,不编译了
#include <__msvc_chrono.hpp>
#include <cstdlib>
#include <system_error>
#include <thread>
#include <utility>
#include <xcall_once.h>
#pragma pack(push, _CRT_PACKING)
// 以下的结构体以及 union 将采用 8 字节对齐。入栈原来的对齐方式 _CRT_PACKING = 8
#pragma warning(push, _STL_WARNING_LEVEL)
// 调整本源文件编译时候的警告级别,是较减少了警告。 _STL_WARNING_LEVEL = 3
// 0 不警告,4 全警告。并把原来的警告级别入栈
#pragma warning(disable : _STL_DISABLED_WARNINGS)
// #define _STL_DISABLED_WARNINGS 4180 4412 4455 4494 4514 4574 ......
// 表示禁用这些警告,忽略这些警告 <yvals_core.h>
_STL_DISABLE_CLANG_WARNINGS
// 按字面意思,禁止 clang 警告,最后还有对应的 宏定义,_STL_RESTORE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new
// 入栈系统之前的 new 的宏定义,并取消此宏定义。可能要自己定义内存管理方式
_STD_BEGIN
// #define _STD_BEGIN namespace std { 表示以下内容全部定义于 std 命名空间
// mutex and recursive_mutex are not supported under /clr
// 在 /clr 下不支持互斥体和 recursive_mutex 。 注意是 ifndef 才编译本文件
#ifndef _M_CEE
class condition_variable;
class condition_variable_any;
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;
};
#endif // _M_CEE
// indicates adopt lock 指示采用锁,具有此标志的构造函数将不再给 mutex 加锁
struct adopt_lock_t { explicit adopt_lock_t() = default; };
// indicates defer lock 指示延迟锁定
struct defer_lock_t { explicit defer_lock_t() = default; };
// indicates try to lock
struct try_to_lock_t { 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 {} ;
//**************************************************************************************************
// _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;
}
};
template <class _Mutex> // 全局函数
void swap(unique_lock<_Mutex>& _Left, unique_lock<_Mutex>& _Right) noexcept
{
_Left.swap(_Right);
}
//****************************************************************************
template <size_t... _Indices, class... _LockN> // 这部分复杂的先暂时不看了
void _Lock_from_locks(const int _Target, index_sequence<_Indices...>, _LockN&... _LkN) // lock _LkN[_Target]
{
int _Ignored[] = {(
(static_cast<int>(_Indices) == _Target ?
(void) _LkN.lock() :
void()
), 0
)...};
(void) _Ignored;
}
template <size_t... _Indices, class... _LockN>
bool _Try_lock_from_locks(
const int _Target, index_sequence<_Indices...>, _LockN&... _LkN) { // try to lock _LkN[_Target]
bool _Result{};
int _Ignored[] = {((static_cast<int>(_Indices) == _Target ? (void) (_Result = _LkN.try_lock()) : void()), 0)...};
(void) _Ignored;
return _Result;
}
template <size_t... _Indices, class... _LockN>
void _Unlock_locks(const int _First, const int _Last, index_sequence<_Indices...>, _LockN&... _LkN) noexcept
/* terminates */ {
// unlock locks in _LkN[_First, _Last)
int _Ignored[] = {
((_First <= static_cast<int>(_Indices) && static_cast<int>(_Indices) < _Last ? (void) _LkN.unlock() : void()),
0)...};
(void) _Ignored;
}
template <class... _LockN>
int _Try_lock_range(const int _First, const int _Last, _LockN&... _LkN)
{
using _Indices = index_sequence_for<_LockN...>;
int _Next = _First;
_TRY_BEGIN
for (; _Next != _Last; ++_Next)
if (!_Try_lock_from_locks(_Next, _Indices{}, _LkN...)) // try_lock failed, backout
{
_Unlock_locks(_First, _Next, _Indices{}, _LkN...);
return _Next;
}
_CATCH_ALL
_Unlock_locks(_First, _Next, _Indices{}, _LkN...);
_RERAISE;
_CATCH_END
return -1;
}
template <class _Lock0, class _Lock1, class _Lock2, class... _LockN>
int _Try_lock1(_Lock0& _Lk0, _Lock1& _Lk1, _Lock2& _Lk2, _LockN&... _LkN)
{ // try to lock 3 or more locks
return _Try_lock_range(0, sizeof...(_LockN) + 3, _Lk0, _Lk1, _Lk2, _LkN...);
}
template <class _Lock0, class _Lock1> // 函数的重载
int _Try_lock1(_Lock0& _Lk0, _Lock1& _Lk1)
{
if (!_Lk0.try_lock()) // 此函数 try 加锁成功则返回 true,锁忙碌则返回 false
return 0;
_TRY_BEGIN // try {
if (!_Lk1.try_lock()) { // if (!_Lk1.try_lock()) {
_Lk0.unlock(); // _Lk0.unlock();
return 1; // return 1;
} // }
_CATCH_ALL // } catch (...) { // 也可能没有错误,捕捉不到错误,不需终止进程
_Lk0.unlock(); // _Lk0.unlock();
_RERAISE; // throw;
_CATCH_END // }
return -1;
}
template <class _Lock0, class _Lock1, class... _LockN>
int try_lock(_Lock0& _Lk0, _Lock1& _Lk1, _LockN&... _LkN)
{ // try to lock multiple locks
return _Try_lock1(_Lk0, _Lk1, _LkN...);
} // 本函尝试加锁成功,返回 -1 。锁忙碌则释放所有的锁,返回0 或 1
//*******************************************************************************************
/*
template <class _Lock0, class _Lock1, class _Lock2, class... _LockN> // lock 3 or more locks, without deadlock
void _Lock_nonmember1(_Lock0& _Lk0, _Lock1& _Lk1, _Lock2& _Lk2, _LockN&... _LkN)
{
int _Hard_lock = 0;
while (_Hard_lock != -1)
_Hard_lock = _Lock_attempt(_Hard_lock, _Lk0, _Lk1, _Lk2, _LkN...);
}
*/
template <class... _LockN> // 该函数不看了,所有注释也一并保留
int _Lock_attempt(const int _Hard_lock, _LockN&... _LkN)
{ // attempt to lock 3 or more locks, starting by locking _LkN[_Hard_lock] and trying to lock the rest
using _Indices = index_sequence_for<_LockN...>;
/*
template <class _Ty, _Ty... _Vals> // sequence of integer parameters
struct integer_sequence { using value_type = _Ty; };
template <class _Ty, _Ty _Size>
using make_integer_sequence = __make_integer_seq<integer_sequence, _Ty, _Size>;
template <size_t _Size>
using make_index_sequence = make_integer_sequence<size_t, _Size>;
template <class... _Types>
using index_sequence_for = make_index_sequence<sizeof...(_Types)>;
*/
_Lock_from_locks(_Hard_lock, _Indices{}, _LkN...);
/*
template <size_t... _Indices, class... _LockN>
void _Lock_from_locks(const int _Target, index_sequence<_Indices...>, _LockN&... _LkN) // lock _LkN[_Target]
{
int _Ignored[] = {(
(static_cast<int>(_Indices) == _Target ?
(void) _LkN.lock() :
void()
), 0
)...};
(void) _Ignored;
}
*/
int _Failed = -1;
int _Backout_start = _Hard_lock; // that is, unlock _Hard_lock
_TRY_BEGIN
_Failed = _Try_lock_range(0, _Hard_lock, _LkN...);
/*
template <class... _LockN>
int _Try_lock_range(const int _First, const int _Last, _LockN&... _LkN)
{
using _Indices = index_sequence_for<_LockN...>;
int _Next = _First;
_TRY_BEGIN
for (; _Next != _Last; ++_Next)
if (!_Try_lock_from_locks(_Next, _Indices{}, _LkN...)) // try_lock failed, backout
{
_Unlock_locks(_First, _Next, _Indices{}, _LkN...);
return _Next;
}
_CATCH_ALL
_Unlock_locks(_First, _Next, _Indices{}, _LkN...);
_RERAISE;
_CATCH_END
return -1;
}
*/
if (_Failed == -1)
{
_Backout_start = 0; // that is, unlock [0, _Hard_lock] if the next throws
_Failed = _Try_lock_range(_Hard_lock + 1, sizeof...(_LockN), _LkN...);
if (_Failed == -1) // we got all the locks
return -1;
}
_CATCH_ALL
_Unlock_locks(_Backout_start, _Hard_lock + 1, _Indices{}, _LkN...);
_RERAISE;
_CATCH_END
// we didn't get all the locks, backout
_Unlock_locks(_Backout_start, _Hard_lock + 1, _Indices{}, _LkN...);
_STD this_thread::yield();
return _Failed;
}
template <class _Lock0, class _Lock1> // 返回值的意思是,若加锁失败,则需要尝试重新加锁,故返回 true。
bool _Lock_attempt_small(_Lock0& _Lk0, _Lock1& _Lk1) // 所以,若加锁成功则本函返回 false
{ // 尝试锁定2个锁,首先锁定_Lk0,然后尝试锁定_Lk1。返回是否再次trv
// attempt to lock 2 locks, by first locking _Lk0, and then trying to lock _Lk1
// returns whether to try again。
_Lk0.lock();
_TRY_BEGIN // try {
if (_Lk1.try_lock()) // if (_Lk1.try_lock()) // 本函加锁成功返 T,锁忙碌返 F
return false; // return false;
_CATCH_ALL // } catch (...) { // 也可能没有错误,捕捉不到错误,不需终止进程
_Lk0.unlock(); // _Lk0.unlock();
_RERAISE; // throw;
_CATCH_END // }
_Lk0.unlock(); // 因为加锁失败,获得的 LK0 锁也释放掉
_STD this_thread::yield(); // // 使本线程让出 CPU
return true; // true 表示本线程再次获得运行时需再次尝试获取这俩锁
}
template <class _Lock0, class _Lock1, class _Lock2, class... _LockN>
void _Lock_nonmember1(_Lock0& _Lk0, _Lock1& _Lk1, _Lock2& _Lk2, _LockN&... _LkN)
{ // 函数重载的复杂情况 lock 3 or more locks, without deadlock
int _Hard_lock = 0;
while (_Hard_lock != -1)
_Hard_lock = _Lock_attempt(_Hard_lock, _Lk0, _Lk1, _Lk2, _LkN...);
}
template <class _Lock0, class _Lock1> // 这是重载的简单情况
void _Lock_nonmember1(_Lock0& _Lk0, _Lock1& _Lk1)
{ // 锁 2 锁,没有死锁,特殊情况下更好的 codegen 和 redu 通用元编程
while ( _Lock_attempt_small(_Lk0, _Lk1) && _Lock_attempt_small(_Lk1, _Lk0)) {}
// 函数 _Lock_attempt_small 加锁成功则返回 false ,加锁失败返回 true
}
template <class _Lock0, class _Lock1, class... _LockN> // lock multiple locks, without deadlock
void lock(_Lock0& _Lk0, _Lock1& _Lk1, _LockN&... _LkN) // 锁定多个锁,无死锁
{ //看源码,本函只有在获取了所有锁之后,才会返回。
_Lock_nonmember1(_Lk0, _Lk1, _LkN...);
} //本函数的实现灵魂是调用 mutex.try_lock(),该函数不会陷入睡眠等待
//***************************************************************************************************
#ifndef _M_CEE
#define _WINDOWS_API __declspec(dllimport) __stdcall
#define _RENAME_WINDOWS_API(_Api) _Api
#endif // _M_CEE
extern "C" int __std_init_once_begin_initialize(
void** _LpInitOnce, unsigned long _DwFlags, int* _FPending, void** _LpContext) noexcept;
// 这两个系统函数都是成功执行返回 true,失败返回 false。 参数名可以见名知意。
// 系统函数__std_init_once_complete(&_Once._Opaque, 控制标志, 可选的上下文环境)
extern "C" int __std_init_once_complete(
void** _LpInitOnce, unsigned long _DwFlags, void* _LpContext) noexcept;
// #define RTL_RUN_ONCE_INIT_FAILED 0x00000004UL
// #define INIT_ONCE_INIT_FAILED RTL_RUN_ONCE_INIT_FAILED
_INLINE_VAR constexpr unsigned long _Init_once_init_failed = 0x4UL; // 初始化失败的标志
struct once_flag // opaque不透明的 data structure for call_once()
{
void* _Opaque; // 含有一个指针类型的数据成员
once_flag() noexcept : _Opaque(nullptr) {} // 默认构造函数
once_flag(const once_flag&) = delete; // 禁止 copy 构造函数
once_flag& operator=(const once_flag&) = delete; // 禁止 copy 赋值运算符函数
};
struct _Init_once_completer // 类似智能指针或 lock_guard,用于析构上面的 once_flag 对象
{ // 本类型的对象是定义在 call_once(...) 函数内的局部对象
once_flag& _Once; // 数据成员,对 once_flag 类型的数据的引用
unsigned long _DwFlags;
~_Init_once_completer() // 析构函数
{
if ( __std_init_once_complete(&_Once._Opaque, _DwFlags, nullptr) == 0 )
_CSTD abort(); // __declspec(noreturn) void __cdecl abort(void);
}
};
// call_once(..) 全局函数,类的静态成员函数,类的可调用对象,都是可以的;
// 但不可以 call_once(...) 类的动态成员函数,因为无法传递对象本身这个参数。
// 在进程全局里生成 once_flag 对象,这里使用其 once_flag对象 的左值引用
template <class _Fn, class... _Args> // call 函数 _Fx(_Ax...) once,只调用形参中的函数一次
void call_once (once_flag& _Once, _Fn&& _Fx, _Args&&... _Ax) // 这一行最重要
noexcept(noexcept(_STD invoke(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...)))
{
int _Pending;
// 看意思,函数仅可以被执行一次的设置,是在这里执行的,这里的 nullptr 也是可选的上下文环境
if ( __std_init_once_begin_initialize(&_Once._Opaque, 0, &_Pending, nullptr) == 0 )
_CSTD abort(); // __declspec(noreturn) void __cdecl abort(void);
if (_Pending != 0) // unsigned long _Init_once_init_failed = 0x4UL;
{
_Init_once_completer _Op{_Once, _Init_once_init_failed}; // 本函数内定义的局部变量
_STD invoke(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...);
_Op._DwFlags = 0;
}
}
#undef _WINDOWS_API
#undef _RENAME_WINDOWS_API
//****************************************************************************************************
// condition_variable, timed_mutex, and recursive_timed_mutex are not supported under /clr
#ifndef _M_CEE
// names for wait returns , cv 含义是 condition_variable 啊
enum class cv_status { no_timeout, timeout }; // 枚举类型
// 本枚举,只是为了区分线程被 nofity 唤醒且拿到锁以后,是没超时醒来,还是发生了超时,仅此而已。
class condition_variable // class for waiting for conditions
{
private:
char _Cnd_storage[72]; //这是一个简化定义,参考了内存对齐与数据量需求等方面
// using _Mtx_t = struct _Mtx_internal_imp_t * ; 对于 mutex 也有类似的定义
// using _Cnd_t = struct _Cnd_internal_imp_t * ; 缺乏该结构的具体定义,只有其指针
// get pointer to _Cnd_internal_imp_t inside _Cnd_storage
_Cnd_t _Mycnd() noexcept { return reinterpret_cast<_Cnd_t>(&_Cnd_storage); }
public:
using native_handle_type = _Cnd_t; // 这是一个指针类型
native_handle_type native_handle() { return _Mycnd() ; } // 返回本类的数据成员的地址
// void __cdecl _Cnd_init_in_situ(_Cnd_t); // 本类的构造函数,初始化本类的的数据成员
// int pthread_cond_init ( pthread_cond_t * cond, pthread_condattr_t * attr ) ;
condition_variable() { _Cnd_init_in_situ( _Mycnd() ); }
// void __cdecl _Cnd_destroy_in_situ(_Cnd_t); // 本类的析构函数,析构 本类的数据成员
// int pthread_cond_destroy ( pthread_cond_t * cond ) ;
~condition_variable() noexcept { _Cnd_destroy_in_situ(_Mycnd()); }
condition_variable(const condition_variable&) = delete; // 禁止 copy 构造函数
condition_variable& operator=(const condition_variable&) = delete; // 禁止 copy 赋值运算符函数
// 函 _Cnd_signal(...) 总返回 _Thrd_success 。 // wake up one waiter
// int pthread_cond_signal ( pthread_cond_t * cond );
void notify_one() noexcept { _Cnd_signal( _Mycnd() ) ; }
// 函 _Cnd_broadcast(...) 总返回 _Thrd_success
// wake up all waiters 将唤醒所有等待锁的线程,这些线程都有机会获取锁,以执行锁后面的代码
// int pthread_cond_broadcast ( pthread_cond_t * cond ) ;
void notify_all() noexcept { _Cnd_broadcast( _Mycnd() ); }
// 线程退出时,会进行释放资源、更新状态或通知其他线程。
// 这些操作常通过线程退出回调、析构函数(如果线程对象有的话)或特定的库函数来实现。
// register this object for release at thread exit 注册此对象以便在线程退出时释放
void _Register(unique_lock<mutex>& _Lck, int * _Ready)
{ // 在线程结束时,若形参 2 ready 不为 true, 则不再执行条件变量的唤醒操作
// void __cdecl _Cnd_register_at_thread_exit(_Cnd_t, _Mtx_t, int*);
_Cnd_register_at_thread_exit( _Mycnd(), _Lck.release()->_Mymtx(), _Ready );
}
// 这两个函数,服务于 async 、future 系列的线程调用。
// unregister this object for release at thread exit 注销此对象以便在线程退出时释放
void _Unregister(mutex& _Mtx)
{ // 功能上 _Unregister 似乎是对应于取消 _Register 的操作:不在线程结束时执行唤醒操作了
// void __cdecl _Cnd_unregister_at_thread_exit(_Mtx_t);
_Cnd_unregister_at_thread_exit( _Mtx._Mymtx() );
}
/*
template <class _Ty>
class _Associated_state //本类存储了线程中函数的返回值
{ // ready 初始化为 0 , 0 表还未 ready ,因函数还未执行
int _Ready; bool _Ready_at_thread_exit; condition_variable _Cond;
// 虚析构函数,其子类 _Packaged_state 与 孙类 _Deferred_async_state 都没明确定义的析构函数
// 可见析构时,若符合线程退出才唤醒的条件,则需要打断 register 的施法,因为函数返回值已经不存在了
virtual ~_Associated_state() { if (_Has_stored_result && !_Ready) _Cond._Unregister(_Mtx); }
virtual void _Do_notify(unique_lock<mutex>* _Lock, bool _At_thread_exit)
{ // 此是虚函数,但从没有被改写过
_Has_stored_result = true;
if (_At_thread_exit) _Cond._Register(*_Lock, &_Ready); // notify at thread exit
else { _Ready = true; _Cond.notify_all(); }
}
};
*/
// int pthread_cond_wait ( pthread_cond_t * cond , pthread_mutex_t * mutex ) ;
// 函 _Cnd_wait(...) 总返回 _Thrd_success,故不用检查返回值。本函被下面的重载调用
void wait(unique_lock<mutex>& _Lck) { _Cnd_wait( _Mycnd(), _Lck.mutex()->_Mymtx() ); }
// wait for signal and test predicate
// wait() 被唤醒后,本线程需再次抢得锁;若断言条件不满足,就继续释放锁,睡眠等待。
// 若 pred() 返回 F,则线程会释放互斥量,并堵塞在本行;若返 true,则线程继续往下执行。
template <class _Predicate> // 第二个参数是函数,例如 lamda 表达式,断言
void wait(unique_lock<mutex>& _Lck, _Predicate _Pred) { while (!_Pred()) wait(_Lck); }
//*****************************************
// wait for signal with timeout 本函是 最基础,是最终被执行的函数!!,被别的成员函数调用
// 经测试,即使使用了限时等待,若超时后,线程依然没有被 notify() 唤醒,还会继续超时睡眠;
// 形参2 的时刻必须是相对于 1970 年的时刻,即使用 system_clock,而不能是 steady_clock 。
// 直到被 notify() 唤醒,且再次拿到了锁。本函的返回值仅仅是提示线程被唤醒时是否发生了超时。
cv_status wait_until(unique_lock<mutex>& _Lck, const xtime * _Abs_time) // !!
{
if (!_Mtx_current_owns(_Lck.mutex()->_Mymtx())) // 看起来是进入等待前要先持有锁
_Throw_Cpp_error(_OPERATION_NOT_PERMITTED);
//int pthread_cond_timedwait ( pthread_cond_t* cond, pthread_mutex_t* mutex, timespec* abstime );
const int _Res = _Cnd_timedwait(_Mycnd(), _Lck.mutex()->_Mymtx(), _Abs_time);//此函不会抛出异常
// enum { _Thrd_success, _Thrd_nomem, _Thrd_timedout, _Thrd_busy, _Thrd_error };
switch (_Res)
{
case _Thrd_success : return cv_status::no_timeout;
case _Thrd_timedout : return cv_status::timeout;
default : _Throw_C_error(_Res);
}
}
// enum class cv_status { no_timeout, timeout };
// wait for duration ,转化为 调用 wait_until(unique_lock<mutex>& _Lck, const xtime* _Abs_time)
template <class _Rep, class _Period> // 如果在超时时间以外还没有收到唤醒通知,则线程会停止阻塞。
cv_status wait_for(unique_lock<mutex>& _Lck, const chrono::duration<_Rep, _Period>& _Rel_time)
{
if ( _Rel_time <= chrono::duration<_Rep, _Period>::zero() )
return cv_status::timeout; // 若形参 2为负值时间,本线程将不再进入睡眠状态,本函直接返回了
_CSTD xtime _Tgt; // struct xtime { long long sec ; long nsec ; };
// 本函的形参 2 是相对于当前时间的时间间隔,圆整成 10天内,相对于 1970年的绝对时刻,存入形参 1;
// 若发生了时长截断,形参2 大于 10 天,则返回 true ,否则返回 false。形参一是左值引用。
// template <class _Rep, class _Period> // int类型最大值 2,147,483,647 约等于 2*10^9 刚好够用
// bool _To_xtime_10_day_clamped( xtime & _Xt, duration<_Rep, _Period> & _Rel_time )
const bool _Clamped = _To_xtime_10_day_clamped(_Tgt, _Rel_time);
const cv_status _Result = wait_until(_Lck, &_Tgt); // 调用了上面注释里的成员函数
if ( _Clamped ) return cv_status::no_timeout; //发生时间截断的线程唤醒,肯定是不会超时的
return _Result;
}
// 这个函数与上面的是一组,都不带断言。没有收到唤醒信号,即使超时也要继续睡眠。
template <class _Clock, class _Duration> // wait until time point,有系统时钟与稳定时钟俩种
cv_status wait_until(unique_lock<mutex>& _Lck, const chrono::time_point<_Clock, _Duration>& _Abs_time)
{
#if _HAS_CXX20
static_assert(chrono::is_clock_v<_Clock>, "Clock type required");
#endif // _HAS_CXX20
for (;;)
{
const auto _Now = _Clock::now(); // 若形参 2是相对于当前时间的过去时,直接返回超时;
if ( _Abs_time <= _Now ) return cv_status::timeout; // 本线程也将不再进入睡眠等待状态
_CSTD xtime _Tgt; // _T_x_1_d_c(...)函把不同时钟里的时刻都转换为相对于 1970年 的绝对时间
(void)_To_xtime_10_day_clamped( _Tgt , _Abs_time - _Now);
const cv_status _Result = wait_until(_Lck, &_Tgt); // 此行只在被 notify唤醒后才会返回
if (_Result == cv_status::no_timeout) return cv_status::no_timeout;//条件变量唤醒
}
}
//*********************以下的函数带断言,以上的函数更简单些
private:
// 未超时下的断言为假则继续睡眠等待直到断言为真; 超时后的条件唤醒则直接返回断言结果,断言为假也不再睡眠
template <class _Predicate> // wait for signal with timeout and check predicate
bool _Wait_until1(unique_lock<mutex>& _Lck, const xtime* _Abs_time, _Predicate& _Pred)
{
while ( !_Pred() )
if (wait_until(_Lck, _Abs_time) == cv_status::timeout)
return _Pred();
return true;
}
// 本函数支持 10 天以上乃至更多天数的断言等待。每 10 天为一个睡眠周期,依次积累。
template <class _Clock, class _Duration, class _Predicate> // 本函数的语义同上,没有变化
bool _Wait_until1( unique_lock<mutex>& _Lck,
const chrono::time_point<_Clock, _Duration>& _Abs_time, _Predicate& _Pred)
{
while ( !_Pred() ) // 先断言一次。先拿到锁以后,再调用 wait_xx 系列的等待函数。
{
const auto _Now = _Clock::now(); // 若形参 2是历史时间则直接返回 false,不再睡眠
if (_Abs_time <= _Now) return false;
_CSTD xtime _Tgt;
const bool _Clamped = _To_xtime_10_day_clamped(_Tgt, _Abs_time - _Now);
if (wait_until(_Lck, &_Tgt) == cv_status::timeout && !_Clamped)
return _Pred();
}
return true;
}
public: // public 以下的成员函数供外界使用
template <class _Predicate> // 这个重载函数最简单,未在私有的成员函数的基础上做任何语句增删
bool wait_until(unique_lock<mutex>& _Lck, const xtime* _Abs_time, _Predicate _Pred)
{
return _Wait_until1(_Lck, _Abs_time, _Pred);
}
template <class _Clock, class _Duration, class _Predicate> // 这个重载函数也很简单
bool wait_until(unique_lock<mutex>& _Lck, const chrono::time_point<_Clock, _Duration>& _Abs_time, _Predicate _Pred)
{
#if _HAS_CXX20
static_assert(chrono::is_clock_v<_Clock>, "Clock type required");
#endif // _HAS_CXX20
return _Wait_until1(_Lck, _Abs_time, _Pred);
}
// 函 _To_absolute_time 的返回值类型是 time_point < steady_clock , duration<long_long,nano> >
// auto _To_absolute_time (const chrono::duration<_Rep, _Period>& _Rel_time )
template <class _Rep, class _Period, class _Predicate>
bool wait_for(unique_lock<mutex>& _Lck, const chrono::duration<_Rep, _Period>& _Rel_time, _Predicate _Pred)
{ // 等待信号,带有超时限制和断言 wait for signal with timeout and check predicate
return _Wait_until1(_Lck, _To_absolute_time(_Rel_time), _Pred);
}
};
//************************************************************************************************************
struct _UInt_is_zero // 本类是可调用对象,实现了括号运算符函数。
{
const unsigned int& _UInt; // 数据成员是左值引用,看来是保存了一个整型数据
bool operator()() const { return _UInt == 0; } // 括号运算符函数,数据为 0 则返回 true
};
// 同时具有 mutex 和 condition_variable 的另一个类是 <future> 中的 保存函数返回值的 _Associated_state<_Ty>
// class for timed mutual exclusion 定时互斥的类 , 本类没有继承 _Mutex_base
class timed_mutex // 同时结合了 mutex 与 condition_variable
{ // _My_locked 的含义是线程对锁加了几次锁。但本 timed_mutex 非递归锁,统计加锁次数无意义,故赋值为全 F。
private: // _My_locked 非 0 表已有线程抢占了临界资源 ;
unsigned int _My_locked ; // 此值为 0 表本线程可以占有临界资源,并修改本值为 非0 。
mutex _My_mutex ; // 此处的 mutex 保护的是对数据成员 _My_locked 的访问的原子性
condition_variable _My_cond ; // 为了实现线程同步, mutex 与条件变量总是同时使用、同时出现。
public:
timed_mutex() noexcept : _My_locked(0) {} // 默认的构造函数。没有显式定义的析构函数
timed_mutex(const timed_mutex&) = delete; // 禁止了 copy 构造函数
timed_mutex& operator=(const timed_mutex&) = delete; // 禁止了 copy 赋值运算符
void lock() // lock the mutex,但本函执行完毕时就释放了 mutex 。本类中的 mutex 成员大部分时间是空闲的。
{ // 本成员函数只是独占地修改了数据成员 _My_locked 的值为 非零。
unique_lock<mutex> _Lock(_My_mutex); // 此行代码的执行,隐含了对 mutex 的加锁成功。
// 意思是即使拿到了锁,但若 _My_locked != 0 ,也要释放锁并等待唤醒。
while ( _My_locked != 0 ) _My_cond.wait(_Lock);
_My_locked = UINT_MAX; // UINT_MAX = 0xffffffff ,本线程拿到临界资源后就修改 _My_locked 为 非0
}
void unlock() // unlock the mutex 本类的释放锁后,还有新的功能就是执行条件变量的唤醒。
{
{ // template <class _Mutex>
// class lock_guard { _Mutex& _MyMutex; ~lock_guard() { _MyMutex.unlock(); } };
lock_guard<mutex> _Lock(_My_mutex); // The lock here is necessary
_My_locked = 0; // 强制加锁,然后把 _My_locked 修改为 0 , 再释放锁
}
_My_cond.notify_one(); // 只唤醒一个等待的线程。
}
bool try_lock() noexcept // try to lock the mutex ,
{ // 本函与 mutex.try_lock(...) 的实现不同,但语义还是相同的。 true 表加锁成功。
lock_guard<mutex> _Lock(_My_mutex); // 此行语句的执行,表示加锁成功
if (_My_locked != 0) return false; // 非 0,返 F,表别的线程在使用临界资源
else {
_My_locked = UINT_MAX ;
return true;
}
}
//******************************
// 本函的语义是 : 在限时内尝试对临界资源加锁,加锁成功则返回 true ;始终加不上则返回 false
template <class _Time> // try to lock the mutex with timeout
bool _Try_lock_until( _Time _Abs_time ) // 本函是最基本的成员函数,被别的成员函数调用
{
unique_lock<mutex> _Lock(_My_mutex); // 加锁成功
// 条件变量 condition_variable 的限时等待的语义是:若未超时下的断言为假,
// 则继续睡眠等待直到断言为真; 超时后的条件唤醒则直接返回断言结果,断言为假也不再睡眠。
if ( ! _My_cond.wait_until(_Lock, _Abs_time, _UInt_is_zero{ _My_locked } ) )
return false;
_My_locked = UINT_MAX;
return true;
}
// try to lock the mutex with timeout 调用上面的更底层的函数,语义完全一样
bool try_lock_until(const xtime* _Abs_time) { return _Try_lock_until(_Abs_time); }
template <class _Clock, class _Duration> // try to lock the mutex with timeout
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
return _Try_lock_until(_Abs_time); // 调用了上面的成员函数
}
template <class _Rep, class _Period> // try to lock for duration
bool try_lock_for(const chrono::duration<_Rep, _Period>& _Rel_time) // 调用上面的成员函数
{
return try_lock_until( _To_absolute_time(_Rel_time) );
}
// 函 _To_absolute_time 的返回值类型是 time_point < steady_clock , duration<long_long,nano> >
// auto _To_absolute_time (const chrono::duration<_Rep, _Period>& _Rel_time )
};
//****************************************************************************************************
// enum { _Mtx_plain=0x01 , _Mtx_try=0x02 , _Mtx_timed=0x04 , _Mtx_recursive=0x100 }; // mutex types
// class _Mutex_base { _Mutex_base(int _Flags = 0) { _Mtx_init_in_situ(_Mymtx(), _Flags | _Mtx_try); } };
// class recursive_mutex : _Mutex_base { recursive_mutex() : _Mutex_base(_Mtx_recursive) {} };
class recursive_timed_mutex // class for recursive timed mutual exclusion
{
private: // _My_locked 非 0 表已有线程抢占了临界资源 ;
unsigned int _My_locked ; // 此值为 0 表本线程可以占有临界资源,并修改本值为 非0 。
mutex _My_mutex ; // 此处的 mutex 保护的是对数据成员 _My_locked 的访问的原子性
condition_variable _My_cond ; // 为了实现线程同步, mutex 与条件变量总是同时使用、同时出现。
thread::id _My_owner ; // 记录本锁已被哪个线程拥有
public:
// 默认的构造函数。没有显式定义的析构函数。_My_locked 的含义是本线程加了几次锁,故初始化为 0 。
recursive_timed_mutex() noexcept : _My_locked(0) {}
recursive_timed_mutex(const recursive_timed_mutex&) = delete; // 禁止 copy 构造函数
recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; // 禁止 copy 赋值运算符函数
void lock() // lock the mutex 。从本函数可以看出:递归锁,加了几次锁,也要解锁几次。!!
{
const thread::id _Tid = this_thread::get_id(); // 获取运行此函数的线程的 id
unique_lock<mutex> _Lock(_My_mutex); // 加锁
if (_Tid == _My_owner) // 若是已经持有锁的线程对锁的重复加锁
{
if (_My_locked < UINT_MAX) // 可见,允许持有锁的线程再次加锁
++_My_locked; // 更新加锁的次数
else // 加锁次数太多,报错。但这个数据非常大, u_int 的最大值。
_Throw_system_error(errc::device_or_resource_busy);
}
else // 未持有锁的线程也想加锁,只能睡眠等待,这符合 锁 的语义,lock()函数的定义
{
while ( _My_locked != 0 ) _My_cond.wait(_Lock); // wait(..) 睡眠前,本线程会释放锁的
_My_locked = 1; // 出了上面的 while 与 wait ,此时当前线程已经获得锁了
_My_owner = _Tid;
}
}
// 可见本模板的 unlock() 函数还兼有 condition_variable.notify() 的功能
void unlock() // unlock the mutex 没把本线程加锁的次数解锁完,就不必唤醒别的等待锁的线程
{
bool _Do_notify = false; // 只有在本线程加锁的次数,全部清零,才可以解锁,否则不解锁
{
lock_guard<mutex> _Lock(_My_mutex); // 缩小了锁保护的代码段
--_My_locked; // 加锁的次数减一
if (_My_locked == 0) {
_Do_notify = true;
_My_owner = thread::id(); // 把记录线程 id 的字段清零
}
}
if ( _Do_notify ) _My_cond.notify_one(); // 唤醒等待的线程
}
bool try_lock() noexcept // try to lock the mutex
{
const thread::id _Tid = this_thread::get_id(); // 获取运行此函数的当前线程的 id
lock_guard<mutex> _Lock(_My_mutex); // 此锁在本函数退出时,解开。
if (_Tid == _My_owner) // 说明获得 锁 的线程,也可以多次调用 try_lock()
{
if (_My_locked < UINT_MAX)
++_My_locked; // 叠加加锁的次数,跟 lock(..) 的功能一样
else
return false;
}
else
{
if (_My_locked != 0) // 若别的线程得不到锁, try_lock 不会 wait 等待,直接返回 false
return false;
else // 说明锁空闲了。没有任何线程占有锁。所以本线程可以占有锁。
{
_My_locked = 1;
_My_owner = _Tid;
}
}
return true;
}
//********************以下函数与时间有关了
template <class _Time> // try to lock the mutex with timeout
bool _Try_lock_until(_Time _Abs_time) // 本函数是最基础的函数,被别的成员函数调用
{
const thread::id _Tid = this_thread::get_id(); // 获取运行此函数的线程的 id
unique_lock<mutex> _Lock(_My_mutex);
if (_Tid == _My_owner) // 说明本线程在获得锁以后,又请求加锁
{
if (_My_locked < UINT_MAX) // 这里说明加上锁了,不用等待
++_My_locked;
else
return false;
}
else // 此时可能锁空闲,成员 _My_owner = 0 ; 也可能是锁被别的线程占有
{ // condition_variable.wait_until(..) 有两个版本,支持不同形式的时间点
if (!_My_cond.wait_until(_Lock, _Abs_time, _UInt_is_zero{ _My_locked }))
return false;
// struct _UInt_is_zero { u_int& _UInt; bool operator()() { return _UInt == 0; } };
_My_locked = 1;
_My_owner = _Tid; // 数据成员 _My_owner 更改为当前线程的 id
}
return true;
}
// try to lock the mutex with timeout , 可见,这俩成员函数的功能完全一样,只是函数名不同
bool try_lock_until(const xtime* _Abs_time) { return _Try_lock_until(_Abs_time); }
template <class _Clock, class _Duration> // try to lock the mutex with timeout
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
return _Try_lock_until(_Abs_time);
}
template <class _Rep, class _Period> // try to lock for duration
bool try_lock_for(const chrono::duration<_Rep, _Period>& _Rel_time)
{
return try_lock_until( _To_absolute_time(_Rel_time) );
}
// 函 _To_absolute_time 的返回值类型是 time_point < steady_clock , duration<long_long,nano> >
// auto _To_absolute_time (const chrono::duration<_Rep, _Period>& _Rel_time )
};
//****************************************************************************************************
#if _HAS_CXX17
template <class... _Mutexes>
class _NODISCARD scoped_lock // 这里似乎是以一个类的方式,来管理多个锁
{ // class with destructor that unlocks mutexes
private:
tuple<_Mutexes&...> _MyMutexes;
public:
// construct and lock
explicit scoped_lock(_Mutexes&... _Mtxes) : _MyMutexes(_Mtxes...) { _STD lock(_Mtxes...); }
// construct but don't lock
explicit scoped_lock(adopt_lock_t, _Mutexes&... _Mtxes) : _MyMutexes(_Mtxes...) {}
~scoped_lock() noexcept
{
_STD apply([](_Mutexes&... _Mtxes) { (..., (void)_Mtxes.unlock()); }, _MyMutexes);
}
scoped_lock(const scoped_lock&) = delete;
scoped_lock& operator=(const scoped_lock&) = delete;
};
template <class _Mutex>
class _NODISCARD scoped_lock<_Mutex>
{
private:
_Mutex& _MyMutex;
public:
using mutex_type = _Mutex;
// construct and lock
explicit scoped_lock(_Mutex& _Mtx) : _MyMutex(_Mtx) { _MyMutex.lock(); }
// construct but don't lock
explicit scoped_lock(adopt_lock_t, _Mutex& _Mtx) : _MyMutex(_Mtx) {}
~scoped_lock() noexcept { _MyMutex.unlock(); }
scoped_lock(const scoped_lock&) = delete;
scoped_lock& operator=(const scoped_lock&) = delete;
};
template <>
class scoped_lock<>
{
public:
explicit scoped_lock() {}
explicit scoped_lock(adopt_lock_t) {}
~scoped_lock() noexcept {}
scoped_lock(const scoped_lock&) = delete;
scoped_lock& operator=(const scoped_lock&) = delete;
};
#endif // _HAS_CXX17
//***************************************************************************************************
#endif // _M_CEE
_STD_END
// #define _STD_END } ,在 std 命名空间里的操作结束
#pragma pop_macro("new")
// 恢复最开始隐藏的 new 宏定义,#pragma push_macro("new")
_STL_RESTORE_CLANG_WARNINGS
// 对应最开始的,此处是恢复 clang 警告
#pragma warning(pop)
// 恢复原来的警告级别 #pragma warning(push, _STL_WARNING_LEVEL)
#pragma pack(pop)
// 恢复原来的内存对齐方式 #pragma pack(push, _CRT_PACKING)
#endif // _STL_COMPILER_PREPROCESSOR,本文件在此 #if 成立时才存在
#endif // _MUTEX_
(46)
谢谢