std::packaged_task 源码分析

15 篇文章 0 订阅

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_调用结果,这就好理解了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值