基于virtual studio编译器的C++标准高级接口async实现 分析future与共享状态以及异步任务的关系

//共享状态的成员
public:
    _Ty _Result;
    exception_ptr _Exception;
    mutex _Mtx;
    condition_variable _Cond;
    bool _Retrieved;
    int _Ready;
    bool _Ready_at_thread_exit;
    bool _Has_stored_result;
    bool _Running;

/*--------------------------------*/

template <class _Fty, class... _ArgTypes>
_NODISCARD future<_Invoke_result_t<decay_t<_Fty>, decay_t<_ArgTypes>...>> async(
    launch _Policy, _Fty&& _Fnarg, _ArgTypes&&... _Args) {
    // manages a callable object launched with supplied policy
    using _Ret   = _Invoke_result_t<decay_t<_Fty>, decay_t<_ArgTypes>...>;
    using _Ptype = typename _P_arg_type<_Ret>::type;
    _Promise<_Ptype> _Pr(
        _Get_associated_state<_Ret>(_Policy, _Fake_no_copy_callable_adapter<_Fty,  _ArgTypes...>(
                                                 _STD forward<_Fty>(_Fnarg), _STD  forward<_ArgTypes>(_Args)...)));
    return future<_Ret>(_Pr._Get_state_for_future(), _Nil());
}
template <class _Ty>
class future : public _State_manager<_Ty> {
    // class that defines a non-copyable asynchronous return object that holds a  value
    using _Mybase = _State_manager<_Ty>;

//_State_manager<>内部
    _Associated_state<_Ty>* _Assoc_state;//指向共享状态的指针
    bool _Get_only_once;

//共享状态是在_Get_associated_state函数内部被new出来的,不同的launch对应不同的_Deferred_async_state或者_Task_async_state它们都是_Packaged_state的子类而_Packaged_state又是共享状态_Associated_state的子类

template <class _Ret, class _Fty>
_Associated_state<typename _P_arg_type<_Ret>::type>* _Get_associated_state(
    launch _Psync, _Fty&& _Fnarg) { // construct associated asynchronous state  object for the launch type
    switch (_Psync) { // select launch type
    case launch::deferred:
        return new _Deferred_async_state<_Ret>(_STD forward<_Fty>(_Fnarg));
    case launch::async: // TRANSITION, fixed in vMajorNext, should create a new  thread here
    default:
        return new _Task_async_state<_Ret>(_STD forward<_Fty>(_Fnarg));
    }
}

// CLASS TEMPLATE _Deferred_async_state
template <class _Rx>
class _Deferred_async_state : public _Packaged_state<_Rx()> {
    // class for managing associated synchronous state for deferred execution from  async
public:
    template <class _Fty2>
    _Deferred_async_state(const _Fty2& _Fnarg) : _Packaged_state<_Rx()>(_Fnarg) {}//_Deferred_async_state构造函数仅仅只是讲要执行的任务函数保存了起来
    template <class _Fty2>
    _Deferred_async_state(_Fty2&& _Fnarg) : _Packaged_state<_Rx()>(_STD  forward<_Fty2>(_Fnarg)) {}
private:
    virtual bool _Has_deferred_function() const noexcept override {
        // this function is considered to be deferred until it's invoked
        return !this->_Running;
    }
    virtual void _Run_deferred_function(unique_lock<mutex>& _Lock) override { //  run the deferred function//延迟策略中重写了这个虚函数
        _Lock.unlock();
        _Packaged_state<_Rx()>::_Call_immediate();//依然是_Call_immediate被执行,但是此时是在单线程中执行的,并没有异步创建一个线程执行这个函数
        _Lock.lock();
    }
};

// CLASS TEMPLATE _Task_async_state
template <class _Rx>
class _Task_async_state : public _Packaged_state<_Rx()> {
    // class for managing associated synchronous state for asynchronous execution  from async
public:
    using _Mybase     = _Packaged_state<_Rx()>;
    using _State_type = typename _Mybase::_State_type;
    template <class _Fty2>
    _Task_async_state(_Fty2&& _Fnarg) : _Mybase(_STD forward<_Fty2>(_Fnarg)) {
        _Task = ::Concurrency::create_task([this]() { // do it now //注意这里异步策略异步任务线程创建其实在这里create_task;而lambda函数其实就相当于异步任务的入口点
            this->_Call_immediate();//这里已经是异步线程调用_Call_immediate了
        });
        this->_Running = true;
   } 
    virtual ~_Task_async_state() noexcept {
        _Wait();
    }
    virtual void _Wait() override { // wait for completion
        _Task.wait();
    }
    virtual _State_type& _Get_value(bool _Get_only_once) override {
        // return the stored result or throw stored exception
        _Task.wait();
        return _Mybase::_Get_value(_Get_only_once);
    }
private:
    ::Concurrency::task<void> _Task;
};
template <class _Ret, class... _ArgTypes>
class _Packaged_state<_Ret(_ArgTypes...)>
    : public _Associated_state<_Ret> { // class for managing associated  asynchronous state for packaged_task
public:
    using _Mybase = _Associated_state<_Ret>;
    using _Mydel  = typename _Mybase::_Mydel;
    template <class _Fty2>
    _Packaged_state(const _Fty2& _Fnarg) : _Fn(_Fnarg) {}
#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
    template <class _Fty2, class _Alloc>
    _Packaged_state(const _Fty2& _Fnarg, const _Alloc& _Al, _Mydel* _Dp)
        : _Mybase(_Dp), _Fn(allocator_arg, _Al, _Fnarg) {}
#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
    template <class _Fty2>
    _Packaged_state(_Fty2&& _Fnarg) : _Fn(_STD forward<_Fty2>(_Fnarg)) {}
#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
    template <class _Fty2, class _Alloc>
    _Packaged_state(_Fty2&& _Fnarg, const _Alloc& _Al, _Mydel* _Dp)
        : _Mybase(_Dp), _Fn(allocator_arg, _Al, _STD forward<_Fty2>(_Fnarg)) {}
#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
    void _Call_deferred(_ArgTypes... _Args) { // set deferred call//这个函数其实和下面的_Call_immediate是几乎一模一样的(除了传递的实参)【这个第二实参代表是否在当前线程退出的时候设置共享状态ready并通知】;
 	   //async的延迟策略没有调用过这个函数,都是走的_Call_immediate
        _TRY_BEGIN
        // call function object and catch exceptions
        this->_Set_value(_Fn(_STD forward<_ArgTypes>(_Args)...), true);
        _CATCH_ALL
        // function object threw exception; record result
        this->_Set_exception(_STD current_exception(), true);
        _CATCH_END
    }
    void _Call_immediate(_ArgTypes... _Args) { // call function object
        _TRY_BEGIN
        // call function object and catch exceptions
        this->_Set_value(_Fn(_STD forward<_ArgTypes>(_Args)...), false);//这里执行任务函数成功就设置返回值给共享状态的_Result成员
        _CATCH_ALL
        // function object threw exception; record result
        this->_Set_exception(_STD current_exception(), false);//如果出现异常就提供current_exception函数给共享状态设置_Exception成员
        _CATCH_END
    }
    const function<_Ret(_ArgTypes...)>& _Get_fn() {
        return _Fn;
    }
private:
    function<_Ret(_ArgTypes...)> _Fn;
};

//通过追踪async实现我们发现vs中所谓的共享状态是在async内部 通过_Get_associated_state创建的,async内部构造并返回了future,future内部有一个指针指向共享状态


那么对于延迟策略下的_Deferred_async_state又是什么时候执行任务函数的呢

//_Associated_state
    virtual void _Wait() { // wait for signal
        unique_lock<mutex> _Lock(_Mtx);
        _Maybe_run_deferred_function(_Lock);
        while (!_Ready) {
            _Cond.wait(_Lock);
        }
    }
void _Maybe_run_deferred_function(unique_lock<mutex>& _Lock) { // run a deferred  function if not already done
        if (!_Running) { // run the function
            _Running = true;
            _Run_deferred_function(_Lock);
        }
//
virtual void _Run_deferred_function(unique_lock<mutex>&) {} // do nothing//基类中这是一个virtual函数,而延迟策略对应的_Deferred_async_state对象重写了这个虚函数

总结:对于延迟策略来说,执行任务函数是通过future对象发起get或者wait调用并最终调用其共享状态的_Run_deferred_function虚函数执行的;在内部 _Packaged_state<_Rx()>::_Call_immediate();在单线程中被同步执行;
而对于异步策略来说,是在async内部创建构造共享状态的过程中,即在共享状态的构造函数内部创建一个异步线程执行_Call_immediate的;这里有人会担心异步任务被执行时可能共享状态还没构造完成,这样异步任务的返回值或者异常状态被设置时会不会造成未定义行为;其实不必担心因为根据对象模型在_Task_async_state状态的构造函数内部其基类已经是构造完成的,_Call_immediate主要操作就是调用
任务函数并把返回值写入共享状态,或者发生异常,就把exception_ptr对象写入共享状态对应的成员;这是其共享状态基类成员其实已经是初始化完成的;而共享状态成员对于任务函数来说是隐藏的,即任务
函数内部应该是无法直接读写共享状态的;所以对共享状态的读写操作由_Call_immediate函数完成;这样就保证了安全!













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
是的,C++ 11 引入了 std::async 函数,可以用它来创建异步任务。std::async 函数的原型如下所示: ```c++ template <class Function, class... Args> std::future<typename std::result_of<Function(Args...)>::type> async(Function&& f, Args&&... args); ``` std::async 函数的作用是创建一个异步任务,并返回一个 std::future 对象,用于获取异步任务的返回值。std::async 函数的第一个参数是要执行的函数,后面的参数是该函数的参数。该函数会在一个新线程中执行,并在执行完成后返回结果。如果该函数抛出异常,则 std::future 对象中会保存该异常信息。 std::async 函数还可以指定执行策略,例如 std::launch::async 表示在新线程中执行异步任务,std::launch::deferred 表示在调用 std::future::get() 函数时执行异步任务。如果不指定执行策略,则由编译器自行决定。 以下是一个使用 std::async 函数创建异步任务的示例: ```c++ #include <iostream> #include <future> int foo(int x) { std::cout << "foo is running in thread " << std::this_thread::get_id() << std::endl; return x + 1; } int main() { std::future<int> result = std::async(std::launch::async, foo, 1); std::cout << "main is running in thread " << std::this_thread::get_id() << std::endl; std::cout << "result is " << result.get() << std::endl; return 0; } ``` 在上面的示例中,使用 std::async 函数创建了一个异步任务 foo,并将参数 1 传递给该函数。执行结果会保存在 std::future 对象中,可以使用 std::future::get() 函数获取异步任务的返回值。在主线程中也输出了一些信息,用于对比异步任务和主线程中的执行情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值