c++ 11 多线程支持 (std::future)

本文详细介绍了C++11引入的std::future类模板,用于访问异步操作的结果。std::future提供了等待、查询和获取异步结果的机制,并支持与std::shared_future的交互。内容涵盖了std::future的构造、析构、赋值、等待、获取结果等关键操作,以及相关示例代码,展示了如何在实际编程中有效利用std::future处理并发任务。
摘要由CSDN通过智能技术生成

定义于头文件 <future>

template< class T > class future;             (1) (C++11 起) 

template< class T > class future<T&>;         (2) (C++11 起) 

template<>  class future<void>;               (3) (C++11 起) 

类模板 std::future 提供访问异步操作结果的机制:

  • (通过 std::async 、 std::packaged_task 或 std::promise 创建的)异步操作能提供一个 std::future 对象给该异步操作的创建者。
  • 然后,异步操作的创建者能用各种方法查询、等待或从 std::future 提取值。若异步操作仍未提供值,则这些方法可能阻塞。
  • 异步操作准备好发送结果给创建者时,它能通过修改链接到创建者的 std::future共享状态(例如 std::promise::set_value )进行。

注意, std::future 所引用的共享状态不与另一异步返回对象共享(与 std::shared_future 相反)。

构造函数

future() noexcept;                             (1) (C++11 起) 

future( future&& other ) noexcept;             (2) (C++11 起) 

future( const future& other ) = delete;        (3) (C++11 起) 

构造 std::future 对象。

1) 默认构造函数。构造无共享状态的 std::future 。构造后, valid() == false 。

2) 移动构造函数。用移动语义,以 other 的共享状态构造 std::future 。构造后 other.valid() == false 。

3) std::future可复制构造 (CopyConstructible) 。

参数

other-获得共享状态来源的另一 std::future

析构函数

~future();                 (C++11 起) 

释放任何共享状态。这表示

  • 若返回对象或提供方保有到其共享状态的最后引用,则析构共享状态;
  • 返回对象或提供方放弃到其共享状态的引用;

移动future对象

future& operator=( future&& other ) noexcept; (1) (C++11 起) 

future& operator=( const future& other ) = delete; (2) (C++11 起) 

赋值另一 future 对象的内容。

1) 释放任何共享状态并移动赋值 other 的内容给 *this 。赋值后, other.valid() == false 且 this->valid() 将产生与 other.valid() 在赋值前相同的值。

2) std::future 不可复制赋值 (CopyAssignable) 。

参数

other-将转移状态给 *this 的 std::future

返回值

*this

从 *this 转移共享状态给 shared_future 并返回它

std::shared_future<T> share() noexcept;

转移 *this 的共享状态,若存在,到 std::shared_future 对象。多个 std::shared_future 对象可引用同一共享对象,这对于 std::future 不可能。

在 std::future 上调用 share 后 valid() == false 。

参数

(无)

返回值

含有先前 *this 所保有的共享状态(若存在)的 std::shared_future 对象,如同以 std::shared_future<T>(std:move(*this)) 构造。

检查 future 是否拥有共享状态

bool valid() const noexcept;   (C++11 起) 

检查期货是否指代共享状态。

这是非默认构造或被移动的期货(例如为 std::promise::get_future() 、 std::packaged_task::get_future() 或 std::async() 所返回)在首次调用 get() 或 share() 前的唯一情况。

若在不指代共享状态的 future 上调用任何析构函数、移动赋值运算符或 valid 以外的成员函数,则行为未定义(尽管鼓励实现在此情况下抛出指示 no_state 的 std::future_error )。从 valid()false 的 future 对象移动是合法的。

参数

(无)

返回值

若 *this 指代共享状态则为 true ,否则为 false 。

等待结果变得可用

void wait() const;                (C++11 起) 

void wait() const;

(C++11 起)

阻塞直至结果变得可用。调用后 valid() == true 。

若调用此函数前 valid()== false 则行为未定义。

参数

(无)

返回值

(无)

异常

(无)

注意

鼓励实现检测调用前 valid == false 的情况并抛出以 std::future_errc::no_state 为 error_condition 的 std::future_error 。

调用示例

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

int fib(int n)
{
    if (n < 3)
    {
        return 1;
    }
    else
    {
        return fib(n - 1) + fib(n - 2);
    }
}

int main()
{
    std::future<int> f1 = std::async(std::launch::async, []()
    {
        return fib(20);
    });
    std::future<int> f2 = std::async(std::launch::async, []()
    {
        return fib(25);
    });

    std::cout << "waiting...\n";
    f1.wait();
    f2.wait();

    std::cout << "f1: " << f1.get() << '\n';
    std::cout << "f2: " << f2.get() << '\n';
}

输出


等待结果,如果在指定的超时间隔后仍然无法得到结果,则返回。 

template< class Rep, class Period >
std::future_status wait_for( 
const std::chrono::duration<Rep,Period>& timeout_duration ) const; (C++11 起) 

等待结果变得可用。阻塞直至经过指定的 timeout_duration ,或结果变为可用,两者的先到来者。返回值鉴别结果的状态。

此函数可能由于调度或资源争议延迟而阻塞长于 timeout_duration

推荐标准库用稳定时钟度量时长。若实现用系统时钟代替,则等待时间可能也对时钟调整敏感。

若调用此函数前 valid()== false 则行为未定义。

参数

timeout_duration-要阻塞的最大时长

返回值

常量解释
future_status::deferred要计算结果的函数仍未启动
future_status::ready结果就绪
future_status::timeout已经过时限

异常

时钟、时间点或时长在执行中可能抛的任何异常(标准库提供的时钟、时间点和时长决不抛出)。

注意

鼓励实现在调用前检测 valid == false 的情况并抛出以 future_errc::no_state 为 error_condition 的 future_error 。

等待结果,如果在已经到达指定的时间点时仍然无法得到结果,则返回。

template< class Clock, class Duration >
std::future_status wait_until(
const std::chrono::time_point<Clock,Duration>& timeout_time ) const;(C++11 起) 

wait_until 等待结果变为可用。它阻塞直至抵达指定的 timeout_time ,或结果变为可用,两者的先到来者。返回值指示 wait_until 为何返回。

若调用此函数前 valid()== false 则行为未定义。

参数

timeout_time-要阻塞到的最大时间点

返回值

常量解释
future_status::deferred要计算结果的函数仍未启动
future_status::ready结果就绪
future_status::timeout已经过时限

异常

时钟、时间点或时长在执行中可能抛的任何异常(标准库提供的时钟、时间点和时长决不抛出)。

注意

鼓励实现在调用前检测 valid == false 的情况并抛出以 future_errc::no_state 为 error_condition 的 future_error 。

使用倾向 timeout_time 的时钟,不要求是单调时钟。若不连续地调节时钟,则不对此函数的行为保证,但既存实现将 timeout_timeClock 转换到 std::chrono::system_clock ,并委托 POSIX pthread_cond_timedwait 以令等待忠实于系统时钟,但非用户提供 Clock 的调节。任何情况下,由于调度或资源争议延迟,函数可能等待长于抵达 timeout_time

调用示例

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

int main()
{
    std::chrono::system_clock::time_point two_seconds_passed
        = std::chrono::system_clock::now() + std::chrono::seconds(2);

    // 做出花 1 秒完成的 future
    std::promise<int> p1;
    std::future<int> f_completes = p1.get_future();
    std::thread([](std::promise<int> p1)
    {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        p1.set_value_at_thread_exit(9);
    },
    std::move(p1)).detach();

    // 做出花 5 秒完成的 future
    std::promise<int> p2;
    std::future<int> f_times_out = p2.get_future();
    std::thread([](std::promise<int> p2)
    {
        std::this_thread::sleep_for(std::chrono::seconds(5));
        p2.set_value_at_thread_exit(8);
    },
    std::move(p2)).detach();

    std::cout << "Waiting for 2 seconds..." << std::endl;

    if (std::future_status::ready == f_completes.wait_until(two_seconds_passed))
    {
        std::cout << "f_completes: " << f_completes.get() << "\n";
    }
    else
    {
        std::cout << "f_completes did not complete!\n";
    }

    if (std::future_status::ready == f_times_out.wait_until(two_seconds_passed))
    {
        std::cout << "f_times_out: " << f_times_out.get() << "\n";
    }
    else
    {
        std::cout << "f_times_out did not complete!\n";
    }

    std::cout << "Done!\n";
}

输出

 
返回结果

T get();   (1) (仅为泛型 future 模板的成员)          (C++11 起) 
T& get();  (2) (仅为 future<T&> 模板特化的成员)      (C++11 起) 
void get();(3) (仅为 future<void> 模板特化的成员)    (C++11 起) 

get 方法等待直至 future 拥有合法结果并(依赖于使用哪个模板)获取它。它等效地调用 wait() 等待结果。

泛型模板和二个模板特化各含单个 get 版本。 get 的三个版本仅在返回类型有别。

若调用此函数前 valid() 为 false 则行为未定义。

释放任何共享状态。调用此方法后 valid() 为 false 。

参数

(无)

返回值

1) 存储于共享状态的值 v ,如同 std::move(v) 。

2) 存储于共享状态的值的引用。

3) 无。

异常

若 future 所引用的共享状态中存储异常(例如,通过调用 std::promise::set_exception() ),则抛出该异常。

注意

鼓励实现在调用前检测 valid() 为 false 的情况,并抛出以 std::future_errc::no_state 为 error_condition 的 std::future_error 。

调用示例

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

std::string time()
{
    static auto start = std::chrono::steady_clock::now();
    std::chrono::duration<double> d = std::chrono::steady_clock::now() - start;
    return "[" + std::to_string(d.count()) + "s]";
}
int main()
{
    {
        std::cout << time() << " launching thread\n";
        std::future<int> f = std::async(std::launch::async, []
        {
            std::this_thread::sleep_for(std::chrono::seconds(1));
            return 7;
        });
        std::cout << time() << " waiting for the future, f.valid() == "
                  << f.valid() << "\n";
        int n = f.get();
        std::cout << time() << " future.get() returned with " << n << ". f.valid() = "
                  << f.valid() << '\n';
    }

    {
        std::cout << time() << " launching thread\n";
        std::future<int> f = std::async(std::launch::async, []
        {
            std::this_thread::sleep_for(std::chrono::seconds(1));
            return true ? throw std::runtime_error("7") : 7;
        });
        std::cout << time() << " waiting for the future, f.valid() == "
                  << f.valid() << "\n";
        try
        {
            int n = f.get();
            std::cout << time() << " future.get() returned with " << n
                      << " f.valid() = " << f.valid() << '\n';
        }
        catch (const std::exception& e)
        {
            std::cout << time() << " caught exception " << e.what()
                      << ", f.valid() == " << f.valid() << "\n";
        }
    }
}

输出

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值