• std::async 源码解析


    本次采用的xcode std++11 对应的源码分析


    async对应的源码

    1. template <class _Fp, class... _Args>
    2. future::type, typename decay<_Args>::type...>::type>
    3. async(_Fp&& __f, _Args&&... __args)
    4. {
    5.     return _VSTD::async(launch::any, _VSTD::forward<_Fp>(__f),
    6.                                     _VSTD::forward<_Args>(__args)...);
    7. }
    8. template <class _Fp, class... _Args>
    9. future::type, typename decay<_Args>::type...>::type>
    10. async(launch __policy, _Fp&& __f, _Args&&... __args)
    11. {
    12.     typedef __async_func::type, typename decay<_Args>::type...> _BF;
    13.     typedef typename _BF::_Rp _Rp;
    14. #ifndef _LIBCPP_NO_EXCEPTIONS
    15.     try
    16.     {
    17. #endif
    18.         if (__does_policy_contain(__policy, launch::async))
    19.         return _VSTD::__make_async_assoc_state<_Rp>(_BF(_VSTD::__decay_copy(_VSTD::forward<_Fp>(__f)),
    20.                                                      _VSTD::__decay_copy(_VSTD::forward<_Args>(__args))...));
    21. #ifndef _LIBCPP_NO_EXCEPTIONS
    22.     }
    23.     catch ( ... ) { if (__policy == launch::async) throw ; }
    24. #endif
    25.         return future<_Rp>{};
    26. }


    先讨论这个,异步执行的__make_async_assoc_state

    C++
    template <class _Rp, class _Fp>
    _LIBCPP_INLINE_VISIBILITY future<_Rp>
    __make_async_assoc_state(_Fp&& __f)
    {
        unique_ptr<__async_assoc_state<_Rp, _Fp>, __release_shared_count>
            __h(new __async_assoc_state<_Rp, _Fp>(_VSTD::forward<_Fp>(__f)));
        _VSTD::thread(&__async_assoc_state<_Rp, _Fp>::__execute, __h.get()).detach();
        return future<_Rp>(__h.get());
    }

    也就是说这个接口返回了future对象,并把__async_assoc_state 指针作为future对象的构造方法传递进去了

    __async_assoc_state

      这个类对象继承了__assoc_state<_Rp>

    重点关注下__on_zero_shared() 这个方法

    C++
    template <class _Rp, class _Fp>
    class _LIBCPP_AVAILABILITY_FUTURE __async_assoc_state
        : public __assoc_state<_Rp>
    {
        typedef __assoc_state<_Rp> base;

        _Fp __func_;

        virtual void __on_zero_shared() _NOEXCEPT;
    public:
        _LIBCPP_INLINE_VISIBILITY
        explicit __async_assoc_state(_Fp&& __f);

        virtual void __execute();
    };
     

     子类__assoc_state

    C++
    template <class _Rp>
    class _LIBCPP_AVAILABILITY_FUTURE _LIBCPP_HIDDEN __assoc_state
        : public __assoc_sub_state
    {
        typedef __assoc_sub_state base;
        typedef typename aligned_storage<sizeof(_Rp), alignment_of<_Rp>::value>::type _Up;
    protected:
        _Up __value_;

        virtual void __on_zero_shared() _NOEXCEPT;
    public:

        template <class _Arg>
        void set_value(_Arg&& __arg);

        template <class _Arg>
        void set_value_at_thread_exit(_Arg&& __arg);

        _Rp move();
        typename add_lvalue_reference<_Rp>::type copy();
    };

    子类__assoc_sub_state

    C++
    class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE __assoc_sub_state
        : public __shared_count
    {
    protected:
        exception_ptr __exception_;
        mutable mutex __mut_;
        mutable condition_variable __cv_;
        unsigned __state_;

        virtual void __on_zero_shared() _NOEXCEPT;
        void __sub_wait(unique_lock& __lk);
    public:
        enum
        {
            __constructed = 1,
            __future_attached = 2,
            ready = 4,
            deferred = 8
        };

        _LIBCPP_INLINE_VISIBILITY
        __assoc_sub_state() : __state_(0) {}

        _LIBCPP_INLINE_VISIBILITY
        bool __has_value() const
            {return (__state_ & __constructed) || (__exception_ != nullptr);}

        _LIBCPP_INLINE_VISIBILITY
        void __attach_future() {
            lock_guard __lk(__mut_);
            bool __has_future_attached = (__state_ & __future_attached) != 0;
            if (__has_future_attached)
                __throw_future_error(future_errc::future_already_retrieved);
            this->__add_shared();
            __state_ |= __future_attached;
        }

        _LIBCPP_INLINE_VISIBILITY
        void __set_deferred() {__state_ |= deferred;}

        void __make_ready();
        _LIBCPP_INLINE_VISIBILITY
        bool __is_ready() const {return (__state_ & ready) != 0;}

        void set_value();
        void set_value_at_thread_exit();

        void set_exception(exception_ptr __p);
        void set_exception_at_thread_exit(exception_ptr __p);

        void copy();

        void wait();
        template <class _Rep, class _Period>
            future_status
            _LIBCPP_INLINE_VISIBILITY
            wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const;
        template <class _Clock, class _Duration>
            _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
            future_status
            wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const;

        virtual void __execute();
    };

    子类__shared_count

    C++
    class _LIBCPP_TYPE_VIS __shared_count
    {
        __shared_count(const __shared_count&);
        __shared_count& operator=(const __shared_count&);

    protected:
        long __shared_owners_;
        virtual ~__shared_count();
    private:
        virtual void __on_zero_shared() _NOEXCEPT = 0;

    public:
        _LIBCPP_INLINE_VISIBILITY
        explicit __shared_count(long __refs = 0) _NOEXCEPT
            : __shared_owners_(__refs) {}

    #if defined(_LIBCPP_BUILDING_LIBRARY) && \
        defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
        void __add_shared() _NOEXCEPT;
        bool __release_shared() _NOEXCEPT;
    #else
        _LIBCPP_INLINE_VISIBILITY
        void __add_shared() _NOEXCEPT {
          __libcpp_atomic_refcount_increment(__shared_owners_);
        }
        _LIBCPP_INLINE_VISIBILITY
        bool __release_shared() _NOEXCEPT {
          if (__libcpp_atomic_refcount_decrement(__shared_owners_) == -1) {
            __on_zero_shared();
            return true;
          }
          return false;
        }
    #endif
        _LIBCPP_INLINE_VISIBILITY
        long use_count() const _NOEXCEPT {
            return __libcpp_relaxed_load(&__shared_owners_) + 1;
        }
    };

    为什么async 执行后 async返回对象销毁时候,必须等待异步任务执行完成呢?

    std::future

    C++
    template <class _Rp>
    class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE future
    {
        __assoc_state<_Rp>* __state_;

        explicit future(__assoc_state<_Rp>* __state);

        template <class> friend class promise;
        template <class> friend class shared_future;

        template <class _R1, class _Fp>
            friend future<_R1> __make_deferred_assoc_state(_Fp&& __f);
        template <class _R1, class _Fp>
            friend future<_R1> __make_async_assoc_state(_Fp&& __f);

    public:
        _LIBCPP_INLINE_VISIBILITY
        future() _NOEXCEPT : __state_(nullptr) {}
        _LIBCPP_INLINE_VISIBILITY
        future(future&& __rhs) _NOEXCEPT
            : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;}
        future(const future&) = delete;
        future& operator=(const future&) = delete;
        _LIBCPP_INLINE_VISIBILITY
        future& operator=(future&& __rhs) _NOEXCEPT
            {
                future(_VSTD::move(__rhs)).swap(*this);
                return *this;
            }

        ~future();
        _LIBCPP_INLINE_VISIBILITY
        shared_future<_Rp> share() _NOEXCEPT;

        // retrieving the value
        _Rp get();

        _LIBCPP_INLINE_VISIBILITY
        void swap(future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);}

        // functions to check state
        _LIBCPP_INLINE_VISIBILITY
        bool valid() const _NOEXCEPT {return __state_ != nullptr;}

        _LIBCPP_INLINE_VISIBILITY
        void wait() const {__state_->wait();}
        template <class _Rep, class _Period>
            _LIBCPP_INLINE_VISIBILITY
            future_status
            wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const
                {return __state_->wait_for(__rel_time);}
        template <class _Clock, class _Duration>
            _LIBCPP_INLINE_VISIBILITY
            future_status
            wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const
                {return __state_->wait_until(__abs_time);}
    };

    这里重点关注下~future() 的西沟方法

    C++
    template <class _Rp>
    future<_Rp>::~future()
    {
        if (__state_)
            __state_->__release_shared();
    }

    __shared_count::__release_shared

    C++
     template<class _Tp> class _LIBCPP_TEMPLATE_VIS weak_ptr;

    class _LIBCPP_TYPE_VIS __shared_count
    {
     bool __release_shared() _NOEXCEPT {
          if (__libcpp_atomic_refcount_decrement(__shared_owners_) == -1) {
            __on_zero_shared();
            return true;
          }
          return false;
        }
     }

    __async_assoc_state::__on_zero_shared

    C++
    template <class _Rp, class _Fp>
    void
    __async_assoc_state<_Rp, _Fp>::__on_zero_shared() _NOEXCEPT
    {
        this->wait();
        base::__on_zero_shared();
    }

    C++
    void
    __assoc_sub_state::wait()
    {
        unique_lock __lk(__mut_);
        __sub_wait(__lk);
    }
     

    C++

    void
    __assoc_sub_state::__sub_wait(unique_lock& __lk)
    {
        if (!__is_ready())
        {
            if (__state_ & static_cast(deferred))
            {
                __state_ &= ~static_cast(deferred);
                __lk.unlock();
                __execute();
            }
            else
                while (!__is_ready())
                    __cv_.wait(__lk);
        }
    }

    也就是说在async 返回的future在西沟方法中最终会调用wait方法,这也就是解释了味了退出的时候会调用wait方法

    Async defer模式

    __make_deferred_assoc_state

    C++
    template <class _Fp, class... _Args>

    future<typename __invoke_of<typename decay<_Fp>::type, typename decay<_Args>::type...>::type>
    async(launch __policy, _Fp&& __f, _Args&&... __args)
    {
        typedef __async_func<typename decay<_Fp>::type, typename decay<_Args>::type...> _BF;
        typedef typename _BF::_Rp _Rp;

        if (__does_policy_contain(__policy, launch::deferred))
            return _VSTD::__make_deferred_assoc_state<_Rp>(_BF(_VSTD::__decay_copy(_VSTD::forward<_Fp>(__f)),
                                                            _VSTD::__decay_copy(_VSTD::forward<_Args>(__args))...));
        return future<_Rp>{};
    }
    template <class _Rp, class _Fp>
    _LIBCPP_INLINE_VISIBILITY future<_Rp>
    __make_deferred_assoc_state(_Fp&& __f)
    {
        unique_ptr<__deferred_assoc_state<_Rp, _Fp>, __release_shared_count>
            __h(new __deferred_assoc_state<_Rp, _Fp>(_VSTD::forward<_Fp>(__f)));
        return future<_Rp>(__h.get());
    }

     

    可以看的出来 它跟async模式不一样,没有直接创建一个thread

    __deferred_assoc_state

    C++
    template <class _Rp, class _Fp>
    class _LIBCPP_AVAILABILITY_FUTURE __deferred_assoc_state
        : public __assoc_state<_Rp>
    {
        typedef __assoc_state<_Rp> base;

        _Fp __func_;

    public:
        _LIBCPP_INLINE_VISIBILITY
        explicit __deferred_assoc_state(_Fp&& __f);

        virtual void __execute();
    };

    __deferred_assoc_state<_Rp, _Fp>::__execute()

    C++
    template <class _Rp, class _Fp>
    void
    __deferred_assoc_state<_Rp, _Fp>::__execute()
    {
    #ifndef _LIBCPP_NO_EXCEPTIONS
        try
        {
    #endif // _LIBCPP_NO_EXCEPTIONS
            this->set_value(__func_());
    #ifndef _LIBCPP_NO_EXCEPTIONS
        }
        catch (...)
        {
            this->set_exception(current_exception());
        }
    #endif // _LIBCPP_NO_EXCEPTIONS
    }

    __execute() 什么时候执行的

     调用wait方法的时候

    C++
    void
    __assoc_sub_state::wait()
    {
        unique_lock __lk(__mut_);
        __sub_wait(__lk);
    }
     

    C++

    void
    __assoc_sub_state::__sub_wait(unique_lock& __lk)
    {
        if (!__is_ready())
        {
            if (__state_ & static_cast(deferred))
            {
                __state_ &= ~static_cast(deferred);
                __lk.unlock();
                __execute();
            }
            else
                while (!__is_ready())
                    __cv_.wait(__lk);
        }
    }

     

  • 相关阅读:
    【图文并茂】Win11正式版如何一键重装系统
    node封装一个图片拼接插件
    结合原理图关于STM32后期例程的更新说明
    图观引擎V3.3.4 功能更强、操作更便捷!最新升级一睹为快
    线段树基本操作——建树+单点修改+区间查询
    说说 Redis pipeline
    错误解决:Process finished with exit code 132 (interrupted by signal 4: SIGILL)
    说实话ThreadLocal真不是啥高级的东西
    【Linux】文件权限的理解
    Jackson 电印迹-蛋白质转移丨膜的类型&WB转移步骤要素
  • 原文地址:https://blog.csdn.net/c553110519/article/details/126232843