std::future类模板的定义
template<class _Ty>
class future: public _State_manager<_Ty>
{...}
future继承自_State_manager,future没有任何数据成员,其内存布局与父类一模一样,为用户提供的公共接口函数实质也是通过继承 _State_manager的函数实现。
1. _State_manager分析
_State_manager类模板用来管理(可能不存在的)关联异步状态对象
私有数据成员:
private:
_Associated_state<_Ty> *_Assoc_state;
bool _Get_only_once;
-
_Assoc_state
:指向关联的异步状态对象_Associated_state是一个线程安全的类,内部通过互斥锁和条件变量实现共享数据的安全同步。
这个类是为c++11高级同步方式(promise/packeged_task/async)提供了底层支持。
-
_Get_only_once
:标识关联的状态是否只能提取一次(std::future)还是多次(std::shared_future)
构造与赋值函数
//默认构造函数,无关联的异步状态,默认允许多次提取关联状态
_State_manager()
: _Assoc_state(nullptr)
{
_Get_only_once = false;
}
//通过关联异步状态对象构造
_State_manager(_Associated_state<_Ty> *_New_state, bool _Get_once)
: _Assoc_state(_New_state)
{
_Get_only_once = _Get_once;
}
//拷贝构造
_State_manager(const _State_manager& _Other, bool _Get_once = false)
: _Assoc_state(nullptr)
{
_Copy_from(_Other);
_Get_only_once = _Get_once;
}
//移动构造
_State_manager(_State_manager&& _Other, bool _Get_once = false)
: _Assoc_state(nullptr)
{
_Move_from(_Other);
_Get_only_once = _Get_once;
}
//拷贝赋值
_State_manager& operator=(const _State_manager& _Other)
{
_Copy_from(_Other);
return (*this);
}
//移动赋值
_State_manager& operator=(_State_manager&& _Other)
{
_Move_from(_Other);
return (*this);
}
拷贝和移动的真正实现:
//拷贝_State_manager
void _Copy_from(const _State_manager& _Other)
{ //防止自我拷贝、赋值
if (this != _STD addressof(_Other))
{
//先判断是否有引用的关联状态
if (_Assoc_state)
_Assoc_state->_Release();
if (_Other._Assoc_state == nullptr)
_Assoc_state = nullptr;
else
{ //增加_Assoc_state对象的引用计数
_Other._Assoc_state->_Retain();
//拷贝数据成员
_Assoc_state = _Other._Assoc_state;
_Get_only_once = _Other._Get_only_once;
}
}
}
//移动_State_manager
void _Move_from(_State_manager& _Other)
{
//防止自我移动、赋值
if (this != _STD addressof(_Other))
{
//先释放*this的关联状态
if (_Assoc_state)
_Assoc_state->_Release();
//将other的关联状态转移到*this
_Assoc_state = _Other._Assoc_state;
_Other._Assoc_state = nullptr;
_Get_only_once = _Other._Get_only_once;
}
}
- 不管是从other拷贝还是移动,都要首先避免自我拷贝、移动
- 不管是从other拷贝还是移动,都要判断是否有引用关联对象
析构:
//如果有关联的异步对象,则释放
~_State_manager() noexcept
{
if (_Assoc_state != nullptr)
_Assoc_state->_Release();
}
状态:
_NODISCARD bool valid() const noexcept
{
return (_Assoc_state != nullptr
&& !(_Get_only_once && _Assoc_state->_Already_retrieved()));
}
_State_manager状态是否有效必须符合:
- 指向关联状态的指针有效
- 关联状态的值——即异步结果——是否被提取
- 如果是std::future,则关联状态只能被提取一次
- 如果是std::shared_future,则与关联状态是否被提取无关
等待异步结果发生:
这些wait系列函数是future和shared_future对应的wait系列函数的真正实现。
void wait() const
{ // wait for signal
if (!valid())
_Throw_future_error(make_error_code(future_errc::no_state));
_Assoc_state->_Wait();
}
template<class _Rep,
class _Per>
future_status wait_for(const chrono::duration<_Rep, _Per>& _Rel_time) const
{ // wait for duration
if (!valid())
_Throw_future_error(make_error_code(future_errc::no_state));
return (_Assoc_state->_Wait_for(_Rel_time));
}
template<class _Clock,
class _Dur>
future_status wait_until(const chrono::time_point<_Clock, _Dur>& _Abs_time) const
{ // wait until time point
if (!valid())
_Throw_future_error(make_error_code(future_errc::no_state));
return (_Assoc_state->_Wait_until(_Abs_time));
}
提取和设置异步状态结果
//提取关联状态的结果---for future::get()/shared_future::get()
_Ty& _Get_value() const
{
if (!valid())
_Throw_future_error(
make_error_code(future_errc::no_state));
return (_Assoc_state->_Get_value(_Get_only_once));
}
//设置关联状态的结果---for promise::set_value()
void _Set_value(const _Ty& _Val, bool _Defer)
{
if (!valid())
_Throw_future_error(
make_error_code(future_errc::no_state));
_Assoc_state->_Set_value(_Val, _Defer);
}
void _Set_value(_Ty&& _Val, bool _Defer)
{
if (!valid())
_Throw_future_error(
make_error_code(future_errc::no_state));
_Assoc_state->_Set_value(_STD forward<_Ty>(_Val), _Defer);
}
2. std::future分析
future类定义不可复制异步返回对象(_State_manager管理(可能不存在的)关联异步状态对象)
future无任何私有数据成员,其提供的接口都是调用父类 _State_manager的函数实现。
构造、赋值、析构
using _Mybase = _State_manager<_Ty>;
...
//默认构造
future() noexcept
{
}
//移动构造--调用父类的移动构造
future(future&& _Other) noexcept
: _Mybase(_STD move(_Other), true)//future is-a _State_manager
{
}
//移动赋值--调用父类的移动赋值
future& operator=(future&& _Right) noexcept
{
_Mybase::operator=(_STD move(_Right));
return (*this);
}
//通过_State_manager构造future
future(const _Mybase& _State, _Nil)
: _Mybase(_State, true)
{
}
//只析构future本身,不会销毁其父类
~future() noexcept
{ //因为future没有数据成员,什么也不做
}
//显示定义future不可拷贝
future(const future&) = delete;
future& operator=(const future&) = delete;
提取关联的异步状态
_Ty get()
{
//移动构造局部future,掏空*this
future _Local{_STD move(*this)};
return (_STD move(_Local._Get_value()));
}
通过std::future::get()提取关联的异步状态结果后,future实例因为以移动构造的方式构造局部future对象(get返回后销毁)之后,将不再可用(future::valid()返回false),并且不能通过future::get()再次提取异步状态结果.
——这并不代表异步状态不再存在,只是无法通过future::get()一次以上
转换为shared_future
_NODISCARD shared_future<_Ty> share() noexcept
{
return (shared_future<_Ty>(_STD move(*this)));
}
share()实质是通过future对象构造了shared_future实例。
shared_future(future<T>&& _Other) noexcept : _Mybase(std::forward<_Mybase>(_Other)) { }
之后future实例的将不再有效,异步状态的访问权转移到新创建的shared_future.
3. std::shared_future分析
shared_future类的定义
template<class _Ty>
class shared_future
: public _State_manager<_Ty>
{}
shared_future类定义可复制异步返回对象,与future一样继承自 State_manager,shared_future也没有任何数据成员,其内存布局与父类一模一样,为用户提供的公共接口函数实质也是通过_State_manager的函数实现.
构造、赋值、析构
shared_future() noexcept
{ // construct
}
//支持拷贝
shared_future(const shared_future& _Other) noexcept
: _Mybase(_Other)
{
}
//支持拷贝复制
shared_future& operator=(const shared_future& _Right) noexcept
{
_Mybase::operator=(_Right);
return (*this);
}
//从future构造
shared_future(future<_Ty>&& _Other) noexcept
: _Mybase(_STD forward<_Mybase>(_Other))
{ // construct from rvalue future object
}
//支持移动构造
shared_future(shared_future&& _Other) noexcept
: _Mybase(_STD move(_Other)) //触发_Mybase移动构造
{
}
//支持移动赋值
shared_future& operator=(shared_future&& _Right) noexcept
{
_Mybase::operator=(_STD move(_Right)); ////触发_Mybase移动赋值
return (*this);
}
~shared_future() noexcept
{ // destroy
}
- 多个shared_future对象可以关联同一个异步状态对象,故shared_future是可拷贝的
- 不管是构造还是赋值,主要是对父类_State_manager的拷贝、移动、赋值
- 前面提过_Get_only_once,除非在构造State_manager时显示设置为true,否则在State_manager实例中默认为false——即异步状态对象可以被多次提取。在构造shared_future时,并未显示的设置 _Get_only_once为ture,故可以通过shared_future多次提取关联的异步状态。
提取关联的异步状态
_Ty& get() const
{
return (*this->_Get_value());//_State_manager::_Get_value
}
与std::future::get()不同的时,调用shared_future::get()不会导致
- shared_future不在有效——因为并未移动shared_future
- 多次get()将报错——因为_Get_only_once为false
4 线程安全性
- 代表异步状态结果的类_Associated_state本身是线程安全的(内部通过互斥锁和条件变量实现共享数据的安全同步)
- future、shared_future本身非线程安全,这是因为其父类_State_manager并非线程安全的。如果多个线程同时操作同一个future、shared_future,比如拷贝、析构、赋值,在没有额外的同步保护机制下,将引发数据竞争。
网友评论