std::packaged_task 源码分析
背景:
c++ 线程池,需要对任务进行包装, packaged_task是不二之选,接下来就分析下源码具体内容
std::packaged_task 源码
C++ template<class _Rp, class ..._ArgTypes> class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE packaged_task<_Rp(_ArgTypes...)> { public: typedef _Rp result_type; // extension //struct __uncvref { // typedef _LIBCPP_NODEBUG_TYPE typename remove_cv<typename remove_reference<_Tp>::type>::type type; //}; template <class _Fp, class = typename enable_if < !is_same< typename __uncvref<_Fp>::type, packaged_task >::value >::type > _LIBCPP_INLINE_VISIBILITY explicit packaged_task(_Fp&& __f) : __f_(_VSTD::forward<_Fp>(__f)) {} private: __packaged_task_function<result_type(_ArgTypes...)> __f_; promise<result_type> __p_; } |
也就说packaged_task 的指针里边有两个__f_, __p_成员,promise我在之前文档已经分析了源码了,这里就不多赘述,接下来对__f_ 这个成员做分析,也就是__packaged_task_function<result_type(_ArgTypes...)>
__packaged_task_function
C++ template<class _Rp, class ..._ArgTypes> class _LIBCPP_AVAILABILITY_FUTURE __packaged_task_function<_Rp(_ArgTypes...)> { typedef __packaged_task_base<_Rp(_ArgTypes...)> __base; typename aligned_storage<3*sizeof(void*)>::type __buf_; __base* __f_;
public: typedef _Rp result_type;
// construct/copy/destroy: _LIBCPP_INLINE_VISIBILITY __packaged_task_function() _NOEXCEPT : __f_(nullptr) {} template<class _Fp> __packaged_task_function(_Fp&& __f); template<class _Fp, class _Alloc> __packaged_task_function(allocator_arg_t, const _Alloc& __a, _Fp&& __f);
__packaged_task_function(__packaged_task_function&&) _NOEXCEPT; __packaged_task_function& operator=(__packaged_task_function&&) _NOEXCEPT;
__packaged_task_function(const __packaged_task_function&) = delete; __packaged_task_function& operator=(const __packaged_task_function&) = delete;
~__packaged_task_function();
void swap(__packaged_task_function&) _NOEXCEPT;
_LIBCPP_INLINE_VISIBILITY _Rp operator()(_ArgTypes...) const; }; |
__packaged_task_function 主要是记录了packaged_task 的可调用对象,或者函数指针之类的,接下来看下它的构造方法的实现
__packaged_task_function 构造方法
C++ template<class _Rp, class ..._ArgTypes> template <class _Fp> __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(_Fp&& __f) : __f_(nullptr) { typedef typename remove_reference<typename decay<_Fp>::type>::type _FR; typedef __packaged_task_func<_FR, allocator<_FR>, _Rp(_ArgTypes...)> _FF; if (sizeof(_FF) <= sizeof(__buf_)) { __f_ = (__base*)&__buf_; ::new (__f_) _FF(_VSTD::forward<_Fp>(__f)); } else { typedef allocator<_FF> _Ap; _Ap __a; typedef __allocator_destructor<_Ap> _Dp; unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); ::new (__hold.get()) _FF(_VSTD::forward<_Fp>(__f), allocator<_FR>(__a)); __f_ = __hold.release(); } } |
可以看的出来如果是函数指针会走上边的if分支,这里__f_ = (__base*)&__buf_;
::new (__f_) _FF(_VSTD::forward<_Fp>(__f)); 完成了函数指针记录到这个packaged_task里边
packaged_task 的构造方法只是记录了调用可调用的对象,后边真正调用的会在operate (),那就看下重写() 实现,就可以知道其原理
packaged_task<_Rp(_ArgTypes...)>::operator()
C++ template<class _Rp, class ..._ArgTypes> void packaged_task<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __args) { ndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS __p_.set_value(__f_(_VSTD::forward<_ArgTypes>(__args)...)); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { __p_.set_exception(current_exception()); } #endif // _LIBCPP_NO_EXCEPTIONS } |
很容易就可以看出来__p_.set_value(__f_(_VSTD::forward<_ArgTypes>(__args)...)); __p_ 记录了__f_调用结果,这就好理解了