c语言编程笔录

首页 >   > 笔记大全

笔记大全

C11的stdfuture对象如何使用

更新时间:2023-12-25

第一段:std::future基础使用

std::future是C++11新增的一个类,用于获取异步操作的返回值。std::future对象表示一个异步计算的未来结果,可以在某个线程中计算值,在另一个线程中等待结果。异步操作通常是通过std::async函数来创建。下面是一个简单的std::future使用示例:

#include 
#include 

int main() {
  auto f = std::async(std::launch::async, []() { return 42; });
  std::cout << "waiting\n";
  auto result = f.get();
  std::cout << "result " << result << std::endl;
  return 0;
}

在这个例子中,我们创建了一个std::async对象来异步执行一个lambda函数,该函数返回整数42。接下来,我们调用f.get()来阻塞当前线程,并等待异步操作的完成。一旦异步操作完成,get方法返回异步操作的结果,并赋值给我们定义的result变量。最后,我们输出result的值。

第二段:std::future异常处理

异步操作可能会发生异常,我们需要对异常进行处理,以避免程序崩溃。对于std::future对象,我们可以使用std::future::wait_for方法或std::future::wait_until方法来检查异步操作的完成状态,如果超时,则返回可以处理的状态,否则返回std::future_status::ready状态。例如:

#include 
#include 
#include 

int main() {
  auto f = std::async(std::launch::async, []() {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    throw std::runtime_error("error");
    return 42;
  });
  std::cout << "waiting\n";
  auto start = std::chrono::system_clock::now();
  auto status = f.wait_for(std::chrono::milliseconds(500));
  if (status == std::future_status::timeout) {
    std::cout << "timeout\n";
  } else {
    try {
      auto result = f.get();
      std::cout << "result " << result << std::endl;
    } catch (const std::runtime_error& e) {
      std::cout << "exception: " << e.what() << std::endl;
    }
  }
  auto end = std::chrono::system_clock::now();
  std::cout << "time " << std::chrono::duration_cast(end - start).count() << "ms\n";
  return 0;
}

在这个例子中,我们异步执行一个lambda函数,该函数在1秒后抛出std::runtime_error异常,并返回整数42。我们设置wait_for等待500毫秒,然后检查异步操作的状态。如果操作还没有完成,wait_for返回std::future_status::timeout状态。否则,我们尝试从std::future对象获取结果,并处理任何可能的异常。

第三段:std::future和std::promise

std::promise和std::future是相辅相成的两个类,提供了一种异步通信机制,可以在不同的线程之间传递值。std::promise对象可以设置值,std::future对象可以获取值。下面是一个使用std::promise和std::future的示例:

#include 
#include 

int main() {
  std::promise p;
  auto f = p.get_future();
  auto thread = std::thread([&p]() { p.set_value(42); });
  std::cout << "waiting\n";
  auto result = f.get();
  std::cout << "result " << result << std::endl;
  thread.join();
  return 0;
}

在这个例子中,我们创建了一个std::promise对象和一个std::future对象。然后,我们在一个新线程中设置promise对象的值。接着我们通过future对象的get方法等待异步操作完成,并获取结果。最后,我们等待新建的线程完成。

第四段:std::future和std::shared_future

std::shared_future是std::future的衍生类,可以让多个线程同时等待同一个异步操作的完成,并获取其结果。std::shared_future对象可以通过std::future::share方法创建。下面是一个使用std::shared_future的示例:

#include 
#include 
#include 

int main() {
  auto f = std::async(std::launch::async, []() {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    return 42;
  });
  std::vector> futures(4);
  for (int i = 0; i < 4; i++) {
    futures[i] = f.share();
  }
  std::cout << "waiting\n";
  for (int i = 0; i < 4; i++) {
    auto result = futures[i].get();
    std::cout << "result " << result << std::endl;
  }
  return 0;
}

在这个例子中,我们异步执行一个lambda函数,该函数在1秒后返回整数42。我们创建了4个std::shared_future对象,每个对象都是使用std::future::share方法从原始std::future对象创建的。我们在四个不同的线程中等待结果,然后打印结果。因为所有的std::shared_future对象都指向相同的异步操作结果,所以它们都可以得到相同的结果。

总结

C++11的std::future类提供了一种异步编程的机制,可以将一个操作绑定到一个future对象上,并通过等待future对象获取操作的结果。同时,std::promise和std::shared_future类可以帮助我们在不同的线程之间传递信息,以实现更复杂的异步操作。在使用std::future类时,我们需要注意处理可能的异常,并谨慎地选择适当的等待方式。