C++多线程:future

std::future

在介绍promisepackaged_task时多次提到future,现在详细介绍该类型
std::future用来获取异步任务的结果,是一种线程间同步的方式,通常由某个Provider创建,Provider在某个线程中设置共享状态的值,与该共享状态相关联的future对象使用std::future::get()获取

一个有效的future对象通常由以下三种Provider创建,并和某个共享状态关联

  • std::promise
  • std::package_task
  • std::async()

构造函数

  • 默认构造函数
    future()noexcept;
    
    std::future默认构造函数构造的future对象是无效的,除非当前的future对象被移动赋值为另一个有效的future对象
  • 拷贝构造函数
    future(const future&)=delete;
    
    被禁用,不可拷贝
  • 移动构造函数
    future(future&&)noexcept;
    

future的拷贝构造和拷贝赋值被禁用,只允许移动拷贝和移动赋值,如下:

std::future<int> fut;
fut= std::async(func);

成员函数

  • std::future::share()
    返回一个shared_future对象,此时的future对象已经不再关联共享状态,即变为无效

    std::future<int> fut= std::async(func);
    std::shared_future<int> shared_fut= fut.share();
    std::cout<<"value:"<<shared_fut.get();
    
  • std::future::get()
    有以下三种形式

    T get()
    R& future<R&>::get()
    void future<void>::get()
    

    若共享状态不为ready,则该函数会阻塞当前线程,直到Provider设置了共享状态的值(状态变为ready),则返回共享状态中的值

  • std::future::valid()
    检查当前future对象是否有效,即是否与某个共享状态相关联

  • std::future::wait()
    等待与当前future对象相关联的共享状态标志变为ready
    若共享状态不为ready,则该阻塞当前线程,直到共享状态变为ready

    std::future<int(int)> fut= std::async(tsk);
    fut.wait();
    
  • future_status std::future::wait_for(const chrono::duration<Rep,Period>&)const;
    设置等待的时间段,若该时间段结束,共享状态仍没有被Provider设置为ready,则当前线程被阻塞,该函数返回如下状态:

    • future_status::ready
      共享状态标志已经变为ready,即Provider设置了共享状态的值
    • future_status::timeout
      超时,在一段时间内共享状态标志未变为ready
    • future_status::deferred
      共享状态包含一个deferred()
      示例如下:
    std::cout<<"checking..."<<std::endl;
    std::chrono::milliseconds span(1000);
    while(fut.wait_for(span)==std::future_status::timeout){
      std::cout<<'.';
    }
    
  • future_status std::future::wait_until(const chrono::time_point<Clock,Duration>&)const;
    设置一个系统绝对时间,返回如下状态:

    future_status::ready
    future_status::timeout
    future_status::deferred
    

std::shared_future

std::future类似,但是std::shared_future允许拷贝,多个shared_future对象可以共享一个共享状态
shared_future可以通过future对象隐式转换,或通过std::future::share()显示转换,转换后,被转换的对象变为无效

构造函数

  • 默认构造函数
    shared_future()noexcept;
    
  • 拷贝构造函数
    shared_future(const shared_future&);
    
  • 移动构造函数
    shared_future(shared_future&&)noexcept;
    

从future对象构造的重载形式

shared_future(future<T>&&)noexcept;

成员函数

operator=()
get()
valid()
wait()
wait_for()
wait_until()

std::async

template <class Fn, class... Args>
future<typename result_of<Fn(Args...)>::type> async(Fn&&, Args&&...);

template <class Fn, class... Args>
future<typename result_of<Fn(Args...)>::type> async(launch, Fn&&, Args&&...);

第一个函数未指定异步任务的启动策略,详见std::launch枚举类型
启动策略函数可以为launch::async()launch::deferred及二者的按位或

  • launch::async
    异步任务会在另一个线程中调用,并通过共享状态返回异步任务的结果
  • launch::deferred
    异步任务将会在共享状态被访问时调用

std::future_error

类型原型

class future_error:public logic_error;

继承自C++标准异常体系的logic_error

其他与std::future相关的枚举类型

enum class future_errc;
enum class future_status;
enum class launch;

std::future_errc

类型 取值 说明
broken_promise 0 与共享状态相关联的std::promise对象在传递值之前被销毁
`future_already_retrieved 1 与共享状态相关联的值已经被Provider获取,即调用了future::get()
promise_already_satisfied 2 std::promise对象已经对共享状态传递了值
no_state 3 无共享状态

std::future_status

主要用在std::futurestd::shared_future)中的wait_for()wait_until()中的

类型 取值 说明
ready 0 共享状态标志
timeout 1 在指定时间内共享状态标志仍没有变为ready
deferred 2 共享状态包含了deferred()

std::launch

主要用在std::async()中,设置异步任务的启动策略

类型 取值 说明
async 0 asynchronous异步任务会在另一个线程中调用,并通过共享状态返回结果
deferred 1 deferred异步任务将会在共享状态被访问时调用,即延时deferred调用

示例如下:

#include <iostream>
#include <future>
#include <chrono>
#include <thread>

void do_print_ten(char c, int ms) {
  for (int i = 0; i < 10; ++i) {
    std::this_thread::sleep_for(std::chrono::milliseconds(ms));
      std::cout << c;
  }
}

int main() {
  std::cout << "with launch::async:\n";
  std::future < void >foo = std::async(std::launch::async, do_print_ten, '*', 100);
  std::future < void >bar = std::async(std::launch::async, do_print_ten, '@', 200);
  // async "get" (wait for foo and bar to be ready):
  foo.get();
  bar.get();
  std::cout << "\n\n";

  std::cout << "with launch::deferred:\n";
  foo = std::async(std::launch::deferred, do_print_ten, '*', 100);
  bar = std::async(std::launch::deferred, do_print_ten, '@', 200);
  // deferred "get" (perform the actual calls):
  foo.get();
  bar.get();
  std::cout << '\n';

  return 0;
}

async

future头文件下,有个async类
用于执行异步任务

int func(int i){
return i+1;
}
auto res= std::async(func,5);
cout<<res.get();
posted @ 2024-11-01 20:09  sgqmax  阅读(5)  评论(0编辑  收藏  举报