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

  • 相关阅读:
    1688普货98%覆盖率,一键生成采购订单,轻松提升采购效率!
    SQL语法之LIKE 操作符
    Dockerfile
    Python中的单例类
    CUDA编程- 矩阵乘法
    相机图像质量研究(40)常见问题总结:显示器对成像的影响--画面泛白
    Spring系列之bean的使用简介说明
    Mybatis 映射器中使用@InsertProvider,@UpdateProvider,@DeleteProvider,@SelectProvider
    Java面向对象
    基于深度学习的面部关键点识别系统
  • 原文地址:https://blog.csdn.net/c553110519/article/details/126439677