C++ 标准库的 std::async 的使用及实现

        

目录

1. std::launch 参数选项

 1.1. std::launch::async

1.2 std::launch::deferred 

1.3 std::launch::async | std::launch::deferred

 2. C++ 标准库的 std::async 的实现

2.1 标准库源码

 2.2 源码分析

3. 总结

        在 C++ 标准库中,std::async 是用于创建并发任务的工具,而第一个参数决定了任务的调度策略。这个参数可以是一个枚举类型,属于 std::launch 枚举类,用于控制如何启动并执行线程任务。常用的值有 std::launch::async 和 std::launch::deferred,你也可以组合这些值来指定不同的执行策略。

1. std::launch 参数选项

 1.1. std::launch::async

  • 描述:std::launch::async 强制任务在新的线程中异步执行,也就是说它会立即启动一个新的线程来执行提供的任务。
  • 执行方式:如果指定了 std::launch::async,任务会在独立的线程中运行,并行执行。
  • 特性:这意味着任务在主线程之外被调度,主线程和新任务可以并行工作。
std::future<int> result = std::async(std::launch::async, threadFunction);

        在上面的代码中,threadFunction 会在新的线程中执行,主线程继续运行而不会被阻塞,除非调用了 result.get() 来等待结果。

1.2 std::launch::deferred 

  • 描述:std::launch::deferred 表示任务执行是“延迟的”。也就是说,任务不会立即启动,而是延迟到调用 std::future 的 get() 或 wait() 时才会执行。

  • 执行方式:如果指定了 std::launch::deferred,任务不会立即在新线程中执行,而是在调用结果时才会执行,且是在调用者的线程中运行(同步执行)。

  • 特性:这种方式可以理解为懒惰执行,只有在需要的时候才去运行任务,且不会在独立的线程中执行。

std::future<int> result = std::async(std::launch::deferred, threadFunction);

        在这个代码中,threadFunction 不会立即执行,而是在调用 result.get() 时才会被执行,并且是在主线程中执行。

1.3 std::launch::async | std::launch::deferred

  • 描述:当使用组合参数 std::launch::async | std::launch::deferred 时,系统可以选择以异步方式执行任务,也可以选择延迟执行,具体由实现(运行时)决定。

  • 执行方式:它可能立即在新的线程中异步执行,也可能延迟到调用 get() 或 wait() 时才执行,这取决于实现的调度策略。通常是由系统根据资源和任务负载来选择合适的策略。

std::future<int> result = std::async(std::launch::async | std::launch::deferred, threadFunction);

        这种使用方式更灵活,但不可预测,因为最终是由系统来决定以哪种方式执行。

 2. C++ 标准库的 std::async 的实现

2.1 标准库源码

_EXPORT_STD template <class _Fty, class... _ArgTypes>
_NODISCARD_ASYNC 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>(_From_raw_state_tag{}, _Pr._Get_state_for_future());
}

_EXPORT_STD template <class _Fty, class... _ArgTypes>
_NODISCARD_ASYNC future<_Invoke_result_t<decay_t<_Fty>, decay_t<_ArgTypes>...>> async(
    _Fty&& _Fnarg, _ArgTypes&&... _Args) {
    // manages a callable object launched with default policy
    return _STD async(launch::async | launch::deferred, _STD forward<_Fty>(_Fnarg), _STD forward<_ArgTypes>(_Args)...);
}

 2.2 源码分析

        在 C++ 标准库的 std::async 的实现代码中,可以看到两个函数模板,它们分别实现了两种形式的 std::async
        (1) 第一种形式允许传递一个显式的 launch 策略。
        (2) 第二种形式没有显式传递 launch 策略,使用默认策略(launch::async | launch::deferred)。
        这两个 async 函数模板用于管理可调用对象的执行,返回一个包含执行结果的 std::future 对象,以便可以在未来的某个时间点获取任务的结果。

  • 模板参数

    • _Fty:类型为调用对象,可以是函数、函数对象、lambda 表达式等。

    • _ArgTypes...:可变参数,用于传递给调用对象的参数。

  • 返回类型

    • 返回类型为 future<_Invoke_result_t<decay_t<_Fty>, decay_t<_ArgTypes>...>>,这是一个 std::future 对象,用于获取调用对象的返回值。

3. 总结

  • std::launch::async:任务会在一个新的线程中立即执行,适用于希望任务异步并行处理的场景。
  • std::launch::deferred:任务延迟执行,直到明确需要时(调用 get() 或 wait())。适用于需要延迟计算,避免无谓的资源消耗。
  • std::launch::async | std::launch::deferred:具体执行策略由系统决定,提供更多的灵活性,但其行为不可预知。

        std::launch 参数的选择取决于任务的特性和系统资源的管理。如果任务是时间消耗型并且需要并发执行,推荐使用 std::launch::async;如果任务不急于执行,可以考虑使用 std::launch::deferred 来节省系统资源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值