1、std::future介绍
类模板 std::future 提供访问异步操作结果的机制:(通过 std::async 、 std::packaged_task 或 std::promise 创建的)异步操作能提供一个 std::future 对象给该异步操作的创建者。然后,异步操作的创建者能用各种方法查询、等待或从 std::future 提取值。若异步操作仍未提供值,则这些方法可能阻塞。异步操作准备好发送结果给创建者时,它能通过修改链接到创建者的 std::future 的共享状态(例如 std::promise::set_value )进行。
注意, std::future 所引用的共享状态不与另一异步返回对象共享(与 std::shared_future 相反)。
—摘抄自https://www.apiref.com/cpp-zh/cpp/thread/future.html
这是官方的定义,那我们就看下具体std::future是怎么回事和怎么使用的吧。
std::future头文件如下:
#include <future>
std::future作用是希望线程返回一个结果,用于异步的操作。
下面,首先看下std::__basic_future 的定义:
/// Common implementation for future and shared_future.
template<typename _Res>
class __basic_future : public __future_base
{
protected:
typedef shared_ptr<_State_base> __state_type;
typedef __future_base::_Result<_Res>& __result_type;
private:
__state_type _M_state;
public:
// Disable copying.
__basic_future(const __basic_future&) = delete;
__basic_future& operator=(const __basic_future&) = delete;
bool
valid() const noexcept { return static_cast<bool>(_M_state); }
void
wait() const
{
_State_base::_S_check(_M_state);
_M_state->wait();
}
template<typename _Rep, typename _Period>
future_status
wait_for(const chrono::duration<_Rep, _Period>& __rel) const
{
_State_base::_S_check(_M_state);
return _M_state->wait_for(__rel);
}
template<typename _Clock, typename _Duration>
future_status
wait_until(const chrono::time_point<_Clock, _Duration>& __abs) const
{
_State_base::_S_check(_M_state);
return _M_state->wait_until(__abs);
}
protected:
/// Wait for the state to be ready and rethrow any stored exception
__result_type
_M_get_result() const
{
_State_base::_S_check(_M_state);
_Result_base& __res = _M_state->wait();
if (!(__res._M_error == 0))
rethrow_exception(__res._M_error);
return static_cast<__result_type>(__res);
}
void _M_swap(__basic_future& __that) noexcept
{
_M_state.swap(__that._M_state);
}
// Construction of a future by promise::get_future()
explicit
__basic_future(const __state_type& __state) : _M_state(__state)
{
_State_base::_S_check(_M_state);
_M_state->_M_set_retrieved_flag();
}
// Copy construction from a shared_future
explicit
__basic_future(const shared_future<_Res>&) noexcept;
// Move construction from a shared_future
explicit
__basic_future(shared_future<_Res>&&) noexcept;
// Move construction from a future
explicit
__basic_future(future<_Res>&&) noexcept;
constexpr __basic_future() noexcept : _M_state() { }
struct _Reset
{
explicit _Reset(__basic_future& __fut) noexcept : _M_fut(__fut) { }
~_Reset() { _M_fut._M_state.reset(); }
__basic_future& _M_fut;
};
};
之后就是我们可以看到,std::future是继承std::__basic_future的,具体的定义如下:
/// Primary template for future.
template<typename _Res>
class future : public __basic_future<_Res>
{
friend class promise<_Res>;
template<typename> friend class packaged_task;
template<typename _Fn, typename... _Args>
friend future<typename result_of<_Fn(_Args...)>::type>
async(launch, _Fn&&, _Args&&...);
typedef __basic_future<_Res> _Base_type;
typedef typename _Base_type::__state_type __state_type;
explicit
future(const __state_type& __state) : _Base_type(__state) { }
public:
constexpr future() noexcept : _Base_type() { }
/// Move constructor
future(future&& __uf) noexcept : _Base_type(std::move(__uf)) { }
// Disable copying
future(const future&) = delete;
future& operator=(const future&) = delete;
future& operator=(future&& __fut) noexcept
{
future(std::move(__fut))._M_swap(*this);
return *this;
}
/// Retrieving the value
_Res
get()
{
typename _Base_type::_Reset __reset(*this);
return std::move(this->_M_get_result()._M_value());
}
shared_future<_Res> share();
};
/// Partial specialization for future<R&>
template<typename _Res>
class future<_Res&> : public __basic_future<_Res&>
{
friend class promise<_Res&>;
template<typename> friend class packaged_task;
template<typename _Fn, typename... _Args>
friend future<typename result_of<_Fn(_Args...)>::type>
async(launch, _Fn&&, _Args&&...);
typedef __basic_future<_Res&> _Base_type;
typedef typename _Base_type::__state_type __state_type;
explicit
future(const __state_type& __state) : _Base_type(__state) { }
public:
constexpr future() noexcept : _Base_type() { }
/// Move constructor
future(future&& __uf) noexcept : _Base_type(std::move(__uf)) { }
// Disable copying
future(const future&) = delete;
future& operator=(const future&) = delete;
future& operator=(future&& __fut) noexcept
{
future(std::move(__fut))._M_swap(*this);
return *this;
}
/// Retrieving the value
_Res&
get()
{
typename _Base_type::_Reset __reset(*this);
return this->_M_get_result()._M_get();
}
shared_future<_Res&> share();
};
/// Explicit specialization for future<void>
template<>
class future<void> : public __basic_future<void>
{
friend class promise<void>;
template<typename> friend class packaged_task;
template<typename _Fn, typename... _Args>
friend future<typename result_of<_Fn(_Args...)>::type>
async(launch, _Fn&&, _Args&&...);
typedef __basic_future<void> _Base_type;
typedef typename _Base_type::__state_type __state_type;
explicit
future(const __state_type& __state) : _Base_type(__state) { }
public:
constexpr future() noexcept : _Base_type() { }
/// Move constructor
future(future&& __uf) noexcept : _Base_type(std::move(__uf)) { }
// Disable copying
future(const future&) = delete;
future& operator=(const future&) = delete;
future& operator=(future&& __fut) noexcept
{
future(std::move(__fut))._M_swap(*this);
return *this;
}
/// Retrieving the value
void
get()
{
typename _Base_type::_Reset __reset(*this);
this->_M_get_result();
}
shared_future<void> share();
};
在C11中,std::future有两种类型的模板。
1、唯一期望值unique futures, std::future<> std::future的实例只能关联一个事件。
2、共享期望值shared futures, std::shared_future<> std::shared_future可以关联多个事件。
异步执行的三种状态如下:
/// Status code for futures
enum class future_status
{
ready,//异步操作已经完成
timeout,//异步操作超时
deferred//异步操作还没有开始
};
这是基本的std::future的定义,下面我们需要看下std::async的定义。
std::async用于启动一个异步执行策略
/// async
template<typename _Fn, typename... _Args>
future<typename result_of<_Fn(_Args...)>::type>
async(launch __policy, _Fn&& __fn, _Args&&... __args)
{
typedef typename result_of<_Fn(_Args...)>::type result_type;
std::shared_ptr<__future_base::_State_base> __state;
if ((__policy & (launch::async|launch::deferred)) == launch::async)
{
__state = __future_base::_S_make_async_state(std::__bind_simple(
std::forward<_Fn>(__fn), std::forward<_Args>(__args)...));
}
else
{
__state = __future_base::_S_make_deferred_state(std::__bind_simple(
std::forward<_Fn>(__fn), std::forward<_Args>(__args)...));
}
return future<result_type>(__state);
}
/// async, potential overload
template<typename _Fn, typename... _Args>
inline future<typename result_of<_Fn(_Args...)>::type>
async(_Fn&& __fn, _Args&&... __args)
{
return async(launch::async|launch::deferred, std::forward<_Fn>(__fn),
std::forward<_Args>(__args)...);
}
/// Launch code for futures
enum class launch
{
async = 1, //保证异步行为,即传递函数在单独的线程中执行。
deferred = 2 //当其他线程调用get()/waite()访问共享状态时,调用非异步的行为。
};
2、std::future重要成员函数介绍
operator= 移动future对象
share 将*this转移共享状态给shared_future并返回它
get获取返回结果
状态
valid() 检查future是否拥有共享状态
wait() 等待执行结果变成可以获得
wait_for() 等待结果,如果在超过指定时间间隔后仍然无法得到结果,则立即返回
3、std::future用法示例
/*************************************************************************
> File Name: thread_future.cpp
> Author: 小和尚敲木鱼
> Mail:
> Created Time: Tue 21 Sep 2021 02:13:25 AM PDT
************************************************************************/
#include <iostream>
#include <thread>
#include <string>
#include <vector>
#include <mutex>
#include <future>
#include <chrono>
using namespace std;
/*****************************文件说明***********************************
************************************************************************/
class Base
{
public:
int baseThread1(int param)
{
int value = 5;
std::cout <<__func__ <<"Reiver param" << param << std::endl;
std::cout << __func__ <<"Current Thread ID = "<< std::this_thread::get_id() << std::endl;
std::chrono::milliseconds sleep_time(500);
std::this_thread::sleep_for(sleep_time);
std::cout << "Current Thread ID ="<< std::this_thread::get_id() << std::endl;
std::cout << "Return = " << (value + param) << std::endl;
return (value + param);
}
int baseThread2()
{
int value = 5;
std::cout <<__func__ <<"Reiver param"<< std::endl;
std::cout << __func__ <<"Current Thread ID = "<< std::this_thread::get_id() << std::endl;
std::chrono::milliseconds sleep_time(500);
std::this_thread::sleep_for(sleep_time);
std::cout << "Current Thread ID ="<< std::this_thread::get_id() << std::endl;
std::cout << "Return = " << value<< std::endl;
return (value);
}
};
int main(int agc,char * agv[])
{
int temp = 20;
Base base_test;
std::cout << "Main Thread ID = " << std::this_thread::get_id() << std::endl;
std::future<int> result = std::async(std::launch::async, &Base::baseThread1, &base_test, temp);
std::cout << "Continue...." << std::endl;
result.wait();
//阻塞在这里,知道result能够获得并得到最后的结果。
//当共享状态值是不可以用时,调用wait接口可以一直阻塞,直到共享状态变为"就绪"时,就变为可以用了。
std::cout << "Final result = " << result.get() << std::endl;
return 0;
}
//OUT
//Main Thread ID = 140522049050432
//Continue....
//baseThread1Reiver param20
//baseThread1Current Thread ID = 140522031671040
//Current Thread ID =140522031671040
//Return = 25
//Final result = 25
std::futere查询状态
//查询future的状态
std::future_status status;
do {
status = future.wait_for(std::chrono::seconds(1));
switch(status)
{
case std::future_status::deferred:
std::cout << "std::future_status::deferred" <<std::endl;
break;
case std::future_status::timeout:
std::cout << "std::future_status::timeout" <<std::endl;
break;
case std::future_status::ready:
std::cout << "std::future_status::ready" <<std::endl;
break;
default:
std::cout << "none status" << std::endl;
break;
}
} while (status != std::future_status::ready);
4、总结
一般来说std::future都是配合std::async、std::packaged_task和std::promise一起使用。返回其异步执行的结果。使用起来也是非常的银杏。
Todo:
后续补充std::future::wait_for的示例。