<future> 注释10:全局函 async (..),由 future<T>.get() 或 future<T>.wait() 驱动来获得延时执行的函数返回值的源代码分析,Task执行则不用被驱动
(34)(35)(36)
·
(34)全局函 async (…) , 接着开始介绍这个重要的函数,使用这个函数,可以从线程中得到函数的返回值。用 thread 类创建的线程是无法从中得到线程中函数的返回值的。
template <class _Fret> // type for functions returning T,本模板处理函数的返回值类型
struct _P_arg_type { using type = _Fret; };
template <class _Fret> // type for functions returning reference to T
struct _P_arg_type<_Fret&> { using type = _Fret*; };
template <> // type for functions returning void
struct _P_arg_type<void> { using type = int; };
//********************************
// manages a callable object launched with supplied policy
template <class _Fty, class... _ArgTypes> // future<T>、future<T&>、future<void> 等
future<_Invoke_result_t<decay_t<_Fty>, decay_t<_ArgTypes>...>> // 函数返回值 // 管理使用提供的策略启动的可调用对象
async(launch _Policy, _Fty&& _Fnarg, _ArgTypes&&... _Args)
{
using _Ret = _Invoke_result_t<decay_t<_Fty>, decay_t<_ArgTypes>...>; // 简写函数的返回值类型
using _Ptype = typename _P_arg_type<_Ret>::type; // 对在线程中执行的函数的返回值的类型进行必要的转换
_Promise<_Ptype> _Pr(_Get_associated_state<_Ret>(_Policy,
_Fake_no_copy_callable_adapter<_Fty, _ArgTypes...>
(_STD forward<_Fty>(_Fnarg), _STD forward<_ArgTypes>(_Args)...)
)
);
/*
_State_manager<Ty> { _Associated_state<Ty>* _Assoc_state; bool _Get_only_once; };
template <class _Ty> // 注意前导的下划线 _Promise
class _Promise
{
_State_manager<_Ty> _State; bool _Future_retrieved; // 函数的返回值是否已交给 future 管理
_Promise(_Associated_state<_Ty>* _State_ptr) // 有参构造函数
: _State(_State_ptr, false), _Future_retrieved(false) {}
// 给 future 后,就不能再通过本 _Promise 使用函数返回值 // 返回结果是左值引用
_State_manager<_Ty>& _Get_state_for_future() { _Future_retrieved = true; return _State; }
};
template <class _Ty>
class future : public _State_manager<_Ty>
{
using _Mybase = _State_manager<_Ty>;
future(const _Mybase& _State, _Nil) : _Mybase(_State, true) {}
};
*/
return future<_Ret>(_Pr._Get_state_for_future(), _Nil()); // 调用了 future 的某版本的构造函数
}
template <class _Fty, class... _ArgTypes> // 推导结果就是 future< 函数返回值 >
future<_Invoke_result_t<decay_t<_Fty>, decay_t<_ArgTypes>...>> // 管理使用默认策略启动的可调用对象
async(_Fty&& _Fnarg, _ArgTypes&&... _Args) // manages a callable object launched启动 with default policy
{
return _STD async( launch::async | launch::deferred,
_STD forward<_Fty>(_Fnarg), _STD forward<_ArgTypes>(_Args)...);
}
++ 看着代码没有几行。但充分的理解代码,需要参考前面几篇文章整理的内容,那些模板类,模板函数。
(35) 由 future.get() 或 future.wait() 驱动来获得延时执行的函数返回值的源代码分析,Task执行则不用被驱动。以下是从各模板类中摘取的简化代码:
template <class _Rx> // 本类是 _Associated_state<T> 的孙子类
class _Deferred_async_state : public _Packaged_state<_Rx()>
{
virtual void _Run_deferred_function(unique_lock<mutex>& _Lock) override { // 虚函数重写
_Lock.unlock();
_Packaged_state<_Rx()>::_Call_immediate();
_Lock.lock();
}
};
template <class _Ty>
class _Associated_state
{ public: using _State_type = _Ty;
_Ty _Result ; mutex _Mtx; condition_variable _Cond;
bool _Retrieved; int _Ready; bool _Running ;
virtual void _Run_deferred_function(unique_lock<mutex>&) {} // do nothing 由子类重写这个函数
void _Maybe_run_deferred_function(unique_lock<mutex>& _Lock) {
if (!_Running) { _Running = true; _Run_deferred_function(_Lock); }
}
virtual _Ty& _Get_value(bool _Get_only_once) {
unique_lock<mutex> _Lock(_Mtx);
if (_Get_only_once && _Retrieved)
_Throw_future_error(make_error_code(future_errc::future_already_retrieved));
_Retrieved = true;
_Maybe_run_deferred_function(_Lock);
while (!_Ready) _Cond.wait(_Lock);
return _Result;
}
virtual void _Wait() {
unique_lock<mutex> _Lock(_Mtx);
_Maybe_run_deferred_function(_Lock); // 执行线程中的函数,以得到返回值
while (!_Ready) _Cond.wait(_Lock); // 循环,直到函数的返回值被准备好
}
};
template <class _Ty>
class _State_manager // future设置 _Get_only_once 为 true
{
_Associated_state<_Ty>* _Assoc_state; bool _Get_only_once;
void wait() { _Assoc_state->_Wait(); } // future<T> 的父类定义了 wait() 成员函数
_Ty& _Get_value() { return _Assoc_state->_Get_value(_Get_only_once); }
};
template <class _Ty> // future<T> 管理的函数返回值只可以被读取一次的原因就在于使用了对象移动构造函数
class future : public _State_manager<_Ty> //futrue管理的 _State_manager._Get_only_once 都为 true
{
future(const _Mybase& _State, _Nil) : _Mybase(_State, true) {}
_Ty get() { future _Local{ _STD move(*this) }; return _STD move(_Local._Get_value()); }
};
// 以上简化代码是对 defer_async_state 的获取函数返回值的执行分析,
// 因没有创建新线程,须由 future<T>.get() 或 future<T>.wait() 驱动来获得函数返回值。
++ 一并给出 vs2019 编辑器整理的注释图片版,或许更易于观察:
++ 在新线程中执行的函数,就不需要 future.get() 来驱动。因为在其构造函数里,新创建了线程,并立马启动了线程中函数的 执行,代码简写如下:
template <class _Ret, class... _ArgTypes> // 只摘取一个重载特化版本
class _Packaged_state<_Ret(_ArgTypes...)> : public _Associated_state<_Ret>
{
function<_Ret(_ArgTypes...)> _Fn; // 传递来的 _Fake_no_copy_callable_adapter 是可调用对象
template <class _Fty2> // 采用的是这个万能引用的版本
_Packaged_state(_Fty2&& _Fnarg) : _Fn(_STD forward<_Fty2>(_Fnarg)) {}
void _Call_immediate(_ArgTypes... _Args) // call function object
{
_TRY_BEGIN // 但根据上下文 args... 是空的
this->_Set_value(_Fn(_STD forward<_ArgTypes>(_Args)...), false);
_CATCH_ALL
this->_Set_exception(_STD current_exception(), false);
_CATCH_END
}
};
template <class _Rx>
class _Task_async_state : public _Packaged_state<_Rx()>
{
::Concurrency::task<void> _Task ; // 这是一个线程,见 并发库摘录.cpp
using _Mybase = _Packaged_state<_Rx()>;
template <class _Fty2>
_Task_async_state(_Fty2&& _Fnarg) : _Mybase(_STD forward<_Fty2>(_Fnarg))
{
_Task = ::Concurrency::create_task([this]() { // do it now lamda表达式
this->_Call_immediate();
});
this->_Running = true;
}
};
(36)
谢谢
更多推荐
已为社区贡献1条内容
所有评论(0)