(18)类 _Deferred_async_state、_Task_async_state ,这两个类,类名都包含 state ,这俩类也是模板类 _Associated_state 的孙子类,也保存了函数的返回值。区分开定义两个孙子类,也是为了区分延时执行函数,和在新线程中执行函数:
// 这是 管理函数返回值的 _Associated_state<T> 的孙子类。要执行的函数是无参的 _Rx() 形式
template <class _Rx> // class for managing associated synchronous state for deferred execution from async
class _Deferred_async_state : public _Packaged_state<_Rx()> // 用于管理从异步延迟执行的关联同步状态的类
{
public: // 指定了函数不带参数的原因在于类 _Fake_no_copy_callable_adapter<T...>
template <class _Fty2> // 构造函数,形参是不带参数的可调用对象。
_Deferred_async_state(const _Fty2& _Fnarg) : _Packaged_state<_Rx()>(_Fnarg) {}
template <class _Fty2> // 构造函数,形参是不带参数的可调用对象。
_Deferred_async_state(_Fty2&& _Fnarg) : _Packaged_state<_Rx()>(_STD forward<_Fty2>(_Fnarg)) {}
private:
// this function is considered to be deferred until it's invoked 此函数被认为是延迟的,直到它被调用
virtual bool _Has_deferred_function() override { return !this->_Running; } // 重写虚函数
virtual void _Run_deferred_function(unique_lock<mutex>& _Lock) override // run the deferred function
{
_Lock.unlock(); // 传递锁进来,是为了解锁,只有写返回值时候才需要加锁。其余时候不必要一直持有锁
_Packaged_state<_Rx()>::_Call_immediate(); // _Call_immediate 中写返回值时 _Set_value(..)会再次加锁
_Lock.lock(); // 获得锁以后再返回,保持语义的一致性;
}
};
// class for managing associated synchronous state for asynchronous execution from async
template <class _Rx>
class _Task_async_state : public _Packaged_state<_Rx()> // 用于管理从异步执行的关联同步状态的类
{
private: // 这里的 task 意思是任务,更指代的是新线程
::Concurrency::task<void> _Task; // 这是一个线程对象,管理新创建的线程
public:
using _Mybase = _Packaged_state<_Rx()>; // 简写父类,同时指出包含的是不带形参的可调用对象。
// 指定了函数不带参数的原因在于类 _Fake_no_copy_callable_adapter<T...>
using _State_type = typename _Mybase::_State_type; //= _Associated_state<_Ty>中的 _Ty函数的返回值类型
template <class _Fty2> // 有参构造函数
_Task_async_state(_Fty2&& _Fnarg) : _Mybase(_STD forward<_Fty2>(_Fnarg)) // do it now
{ // lamda 表达式,创建线程任务,为本类的数据成员线程对象赋值
_Task = ::Concurrency::create_task([this]() { this->_Call_immediate(); } );
this->_Running = true; // 在构造函数中启动了新线程,来执行函数 _Call_immediate()
}
// wait for completion,封装了未知函数 task.wait(..) 函数返回值未计算出来,本对象不予以析构,一直存在
virtual void _Wait() override { _Task.wait(); }
virtual ~_Task_async_state() noexcept { _Wait(); } // 析构函数,调用了 wait 等待
// return the stored result or throw stored exception
virtual _State_type& _Get_value(bool _Get_only_once) override
{
_Task.wait(); // 函数重写,在爷爷类的同名函数里,加了 等待函数执行完毕的 wait(..)
return _Mybase::_Get_value(_Get_only_once);
}
};
(19)推导函数返回值的类 _Invoke_result_t<Fn,arg…> , 引入 async 函数后,可以保存函数的返回值,首先是 编译器可以推断出函数的返回值类型。 STL 库大师们写的优秀极棒的代码,可以充分利用 C++ 的诸多语法,来推导出函数的返回值类型,就是接着这个类的定义。
++ 以下给出此模板类的源代码:
//***************************************以这样的注释行来区分模板类的逻辑**********************************************
template <class _Callable> // decltype 推断出了 函数 callable 的返回值类型
using _Decltype_invoke_zero = decltype(_STD declval<_Callable>()());
//------------------------------
template <class _Result, bool _Nothrow> // result 的语义是实际绑定到 function<T> 对象的函数的返回值类型
struct _Invoke_traits_common // 无参特化版本的父类,也是有参特化版本的父类
{
using type = _Result;
using _Is_invocable = true_type;
template <class _Rx> // 函数是否可调用要分析这一行, _Rx 是 function 的模板参数对应的函数的返回值类型。
using _Is_invocable_r = bool_constant< // 判断转换方向 type ---> _Rx
disjunction_v< is_void<_Rx>, _Invoke_convertible<type, _Rx>
>
};
//-------------------------------
template <class _Void, class _Callable> // 无参泛化版本 , 大致看到都给出了否定语义,不支持函数执行
struct _Invoke_traits_zero // selected when _Callable isn't callable with zero _Args
{
using _Is_invocable = false_type;
template <class _Rx>
using _Is_invocable_r = false_type;
};
template <class _Callable> // 无参特化版本,这是比较好理解的版本。注意给 void_t 提供了两个类型。
struct _Invoke_traits_zero< void_t<_Decltype_invoke_zero<_Callable>> , _Callable > // 出现继承
: _Invoke_traits_common<_Decltype_invoke_zero<_Callable>, noexcept(_STD declval<_Callable>()())> {};
//****************************************************************************************************************
template <class _Callable, class _Ty1, class... _Types2>
using _Decltype_invoke_nonzero = decltype( // 依然是推断被调函数的函数定义时候的返回值类型,函数带参数时候的
_Invoker1<_Callable, _Ty1>::
_Call(_STD declval<_Callable>(), _STD declval<_Ty1>(), _STD declval<_Types2>()...)
);
//------------------------------------------
template <class _Void, class... _Types> // 带形参泛化版本,不支持带参函数执行的 泛化版本,大多给出了否定语义
struct _Invoke_traits_nonzero // selected when _Callable isn't callable with nonzero _Args
{
using _Is_invocable = false_type;
using _Is_nothrow_invocable = false_type;
template <class _Rx>
using _Is_invocable_r = false_type;
};
template <class _Callable, class _Ty1, class... _Types2> // 带形参特化版本,也是程序不报错时选择的版本
struct _Invoke_traits_nonzero<
void_t<_Decltype_invoke_nonzero<_Callable, _Ty1, _Types2...>>, //若此行的推断有语义,就是void
_Callable, // callable 是待执行的函数类型
_Ty1, // 注意,这里存在对函数的参数包的展开
_Types2...
>
: _Invoke_traits_common<
_Decltype_invoke_nonzero< _Callable, _Ty1, _Types2...>,
noexcept(_Invoker1<_Callable, _Ty1>::
_Call(_STD declval<_Callable>(), _STD declval<_Ty1>(), _STD declval<_Types2>()...))
> {};
//**********************************************************************************************************
template <class _Callable, class... _Args>
using _Select_invoke_traits = conditional_t<sizeof...(_Args) == 0,
_Invoke_traits_zero<void, _Callable>,
_Invoke_traits_nonzero<void, _Callable, _Args...>
>;
template <class _Callable, class... _Args>
using _Invoke_result_t = typename _Select_invoke_traits<_Callable, _Args...>::type;
//*******************************************************************************************************************
++下面再给出 vs2019 的注释缩略图,更易于观察:
++ 在上图中的类型推导中,用到的 decltype ( …) 的使用来确定函数的返回值。以及 void_t 的使用,见本系列的别的文章,对其有详细的说明。
(20)
谢谢