(9) # if defined ( ) :
(10) # error " Unsupported platform ! " :
++ 再举例:
(11) 函 _Throw_C_error () 的输出形式 ,一些 STL 的库函数的执行结果需要被检查。正确则是可以的,错误则需要终止程序。那么报错后是什么样子的呢?
++ 报错结果如下:
(12) 类 mutex 与 类 lock_guard 的源码和注释。因为这里的互斥量太多,虽然在 STL 库里是在一个头文件,这里还是拆开展示,代码短也好阅读。因为 lock_guard 的源代码也不长,附在一块给出,同理还有 recursive_mutex 的源码与介绍 :
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);
} // _in_situ 应该是在原位初始化的意思
// void __cdecl _Mtx_destroy_in_situ(_Mtx_t);
~_Mutex_base() { _Mtx_destroy_in_situ( _Mymtx() ); } // 析构函数
_Mutex_base(const _Mutex_base&) = delete; // 禁止 copy 构造函数
_Mutex_base& operator=(const _Mutex_base&) = delete; // 禁止 copy 赋值运算符函数
void lock()
{ // int __cdecl _Mtx_lock(_Mtx_t);当此函数返回 _Thrd_success 时才不报错
_Check_C_return( _Mtx_lock( _Mymtx() ) );
}
// int __cdecl _Mtx_unlock(_Mtx_t); 此函总返回 _Thrd_success
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* ;
native_handle_type native_handle()
{ // void* __cdecl _Mtx_getconcrtcs( _Mtx_t );
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;
};
// indicates adopt lock 指示采用锁,具有此标志的构造函数将不再给 mutex 加锁
struct adopt_lock_t { explicit adopt_lock_t() = default; };
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;
};
// 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(); }
};
(13) 给出这些锁的重复加锁的实验:
++ 可见,当一个线程里的多个函数处于同一个调用链上,可能都要操作共享数据,存在重复加锁的可能性时,需要用 recursive_mutex 才不会报错。
(14)
谢谢