• std::packaged_task 源码分析


    std::packaged_task 源码分析

    背景:

    c++ 线程池,需要对任务进行包装, packaged_task是不二之选,接下来就分析下源码具体内容

    std::packaged_task 源码

    C++
    template
    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::type>::type type;
        //};
    template           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 __f_;
        promise                                __p_;
        
     }
     

    也就说packaged_task 的指针里边有两个__f_, __p_成员,promise我在之前文档已经分析了源码了,这里就不多赘述,接下来对__f_ 这个成员做分析,也就是__packaged_task_function

    __packaged_task_function 

    C++
    template
    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
          __packaged_task_function(_Fp&& __f);
        template
          __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
    template
    __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(_Fp&& __f)
        : __f_(nullptr)
    {
        typedef typename remove_reference::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
    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_调用结果,这就好理解了

  • 相关阅读:
    Horizontal Pod Autoscaler(HPA)
    网站风格变黑白的方法,用css或javascript方法将网站改为灰色
    Spring Cloud Alibaba——Sentinel持久化和集群流控
    总结:Prometheus之PromQL操作符
    Pytorch 中 Dataset 和 DataLoader,以及 torchvision 的 datasets 完全理解
    openGauss学习笔记-79 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT应用场景
    QComboBox的信号
    开播了!大行都在用的最新反欺诈技术大揭密!
    Java反序列化之CommonsCollections(CC1)分析篇
    vue中keep-alive怎么清除组件的缓存
  • 原文地址:https://blog.csdn.net/c553110519/article/details/126439677