<future> 注释3:conditional_t<T...>,void_t<T> 用于构成特化模板,存储函数返回值的爷爷基类 _Associated_state<_Ty>及成函 abandon()

(14) 模板 conditional_t<T…> ,定义于 < xtr1common > , 在本 模板里也会用到:

在这里插入图片描述

(15)void_t 用于构成特化模板,只要 T 可以被编译器推断为某种类型,void_t 就有意义。 STL 库大师们写的代码,多结合 decltype 来完成类型推断。 当然 T 为空也可以。但为空与 decltype 推断不出来,是两回事。本头文件也用到了,简化逻辑,举例学习一下:
其定义如下:

在这里插入图片描述

++ 举例:

在这里插入图片描述

++ 再举例测试,学习 void_ :

在这里插入图片描述

(16) 存储函数返回值的爷爷基类 _Associated_state<_Ty> , 使用 thread 类来创建线程,没法获得函数的返回值。所以 STL 库又新增了别的具有存储线程中函数返回值的精巧的类。就是该类及其儿子类,孙子类。其子孙类,又扩展了数据成员,存储了可调用对象。这样堆区中的本系列对象,就既存储了线程中的可执行对象,又可以存储函数的返回值了。以下给出其带注释的源码:

template <class _Ty>     // 模板参数 _Ty 与线程中执行的函数的返回值类型有关。本类的对象建立在堆区。
class _Associated_state  // class for managing associated synchronous state 用于管理关联同步状态的类
{ 
public:
    using _State_type = _Ty; // 函数返回值则 _Ty是对象类型; 返回左值引用则 _Ty是地址; 返回 void则 _Ty是 int
    using _Mydel = _Deleter_base<_Ty>;

    _Ty _Result; // 当执行函数没有返回值, 则 _Ty 是 int , result 取值为 1 ,表函数执行成功。              
    exception_ptr _Exception;
    mutex _Mtx;  // 线程获得锁以后才可以读写 _Associated_state 指针指向对象的这些数据成员
    condition_variable _Cond;   // 用于线程同步
    bool _Retrieved;            // 表函数返回值是否被读取过

    int  _Ready;                // 表示函数返回值是否已计算好,可以等待读取了, 初始化为 0 = false ,未准备好
    bool _Ready_at_thread_exit; // 是否要待线程结束才允许函数返回值被读取,但代码里貌似未使用,可以用 !_Ready 替代

    bool _Has_stored_result;    // 先后将 _Has_stored_result 与 _Ready 都设置后外界才可以读取函数返回值
    bool _Running;              // 表计算函数返回值的线程是否已启动执行,初始化为  false 

private:
    _Atomic_counter_t _Refs;    // using _Atomic_counter_t = unsigned long;
         // future 的父类 _State_manager 的 copy 构造与赋值运算符函数,就是仅仅将 _Refs 加一。堆区仅有此一份结果。
    _Mydel* _Deleter;           // 初始化为 nullptr ,表程序员未使用自己编写的 删除器 ,用的系统默认版本。

    void _Delete_this()  // delete this object 销毁本模板类的对象自身(也存在父类指针指向子类对象)
    {
        if (_Deleter)  _Deleter->_Delete(this);
        else           delete this; 
    }

    // overridden by _Deferred_async_state 这俩虚函数仅由孙类 _Deferred_async_state 进行了重定义
    // 字面意思就是线程中的函数是否被延迟执行了,是则返回 true
    virtual bool _Has_deferred_function() const noexcept {  return false;  } 
/*
template <class _Rx> // 用于管理从异步延迟执行的关联同步状态的类, 此类改写了这俩虚函数
class _Deferred_async_state : public _Packaged_state<_Rx()> // 本类是 _Associated_state 的孙子类
{   
    virtual bool _Has_deferred_function() override {  return  ! this->_Running;   }

    virtual void _Run_deferred_function(unique_lock<mutex>& _Lock) override  // run the deferred function
    {
        _Lock.unlock();
        _Packaged_state<_Rx()>::_Call_immediate();
        _Lock.lock();
    }
};

template <class _Ty>
class _Associated_state
{
    virtual void _Run_deferred_function(unique_lock<mutex>&) {}  // do nothing 由子类重写这个函数

    void _Maybe_run_deferred_function(unique_lock<mutex>& _Lock) // 运行一个延迟函数(如果还没有完成)
    {
        if (!_Running) // run the function
        {
            _Running = true;
            _Run_deferred_function(_Lock);
        }
    }
};
*/
    virtual void _Run_deferred_function(unique_lock<mutex>&) {} // do nothing 由子类重写这个函数

protected:
    // set ready status at thread exit  未见到哪里调用了此函数。本函就是给 _Ready 成员赋值了 
    void _Make_ready_at_thread_exit() {  if (_Ready_at_thread_exit)   _Ready = true;  }

    // run a deferred function if not already done // 运行一个延迟函数(如果还没有完成)
    void _Maybe_run_deferred_function(unique_lock<mutex>& _Lock) 
    {   // 对于正在运行的线程中的函数,本函什么也不做                                                  
        if (!_Running) {  _Running = true;    _Run_deferred_function(_Lock);  }
    }

public:
    // non-atomic initialization 构造函数。本类默认模板参数 _Ty 是可构造的,对 _Ty 采用默认构造。
    _Associated_state(_Mydel* _Dp = nullptr) : _Refs(1),  _Exception(), _Retrieved(false), _Ready(false), 
        _Ready_at_thread_exit(false), _Has_stored_result(false), _Running(false), _Deleter(_Dp) { }

    _Associated_state(const _Associated_state&) = delete;            // 禁止 copy 构造函数
    _Associated_state& operator=(const _Associated_state&) = delete; // 禁止 copy 赋值运算符

    virtual ~_Associated_state() noexcept  // registered for release at thread exit 析构函数
    {   // 本类存储了线程中函数的返回值。若本类析构时函数返回值没 ready,则不再执行条件变量的唤醒操作
        if (_Has_stored_result && !_Ready) {  _Cond._Unregister(_Mtx);  }
    } 

    void _Retain() { _MT_INCR(_Refs); } // increment reference count 原子性的递增对本对象的引用计数

    // decrement reference count and destroy when zero 原子性的递减变量的值
    void _Release() {  if (_MT_DECR(_Refs) == 0)    _Delete_this();  }
    // 当没有别处继续引用本对象时,销毁、析构本储存函数返回值的堆区对象。

public:
    bool _Is_ready() const { return _Ready != 0; } // 也可直接返回 _Ready,进行默认的类型转换 

    bool _Is_ready_at_thread_exit()   const { return _Ready_at_thread_exit; }

    bool _Already_has_stored_result() const { return _Has_stored_result;    }

    bool _Already_retrieved()         const { return _Retrieved;            }

    void _Abandon() // 本函的语义可能是当没计算出函数返回值时,本对象就被析构释放,
    {               // 则设置 _Associated_state<T>._Exception 成员,以记录此异常情况。
        unique_lock<mutex> _Lock(_Mtx); 
                    // 经测试本函代码的完整执行,仍是正常情况,不会导致进程出错退出。
        if (!_Has_stored_result) {      
            future_error _Fut(make_error_code(future_errc::broken_promise));
            _Set_exception_raw(_STD make_exception_ptr(_Fut), &_Lock, false);
        }   
    }

    //********以下函数是一组,等待与限时等待********

    // 调用本函数的线程会睡眠等待,等待函数返回值的生成。future.wait() 的调用会传递到本函数
    virtual void _Wait()  // wait for signal  本函会促使函数执行, 以求返回值
    { 
        unique_lock<mutex> _Lock(_Mtx);

        _Maybe_run_deferred_function(_Lock); // 执行线程中的函数,以得到返回值

        while (!_Ready)    _Cond.wait(_Lock); // 循环,直到函数的返回值被准备好
    }

    struct _Test_ready   // wraps _Associated_state  类中类,下面的函数会用到
    {
        const _Associated_state* _State;

        _Test_ready(const _Associated_state* _St) : _State(_St) {} // 有参构造函数
        
        bool operator()() const { return _State->_Ready != 0;  } // 已 ready 则返回 true      
    };

    // enum class future_status { ready , timeout , deferred };
    template <class _Rep, class _Per>   // wait for duration
    future_status _Wait_for(const chrono::duration<_Rep, _Per>& _Rel_time)
    {
        unique_lock<mutex> _Lock(_Mtx);

        if (_Has_deferred_function())    return future_status::deferred; // 延时执行的函数

        if (_Cond.wait_for(_Lock, _Rel_time, _Test_ready(this)))
            return future_status::ready; // 函数已经执行完毕,返回值已经准备好了

        return future_status::timeout;   // 正在执行的函数,还没有返回值
    }

    template <class _Clock, class _Dur>  // wait until time point
    future_status _Wait_until(const chrono::time_point<_Clock, _Dur>& _Abs_time)
    { 
        unique_lock<mutex> _Lock(_Mtx);

        if (_Has_deferred_function())  return future_status::deferred;

        if ( _Cond.wait_until(_Lock, _Abs_time, _Test_ready(this)) )
            return future_status::ready;

        return future_status::timeout;
    }

    //***************************************

    // 本函数可以被子类修改,但目前并没有被三个子类修改,所以本代码有效
    virtual _Ty& _Get_value( bool _Get_only_once )   
    {   
        unique_lock<mutex> _Lock(_Mtx);

        if (_Get_only_once && _Retrieved) 
            _Throw_future_error(make_error_code(future_errc::future_already_retrieved));

        if (_Exception)    _Rethrow_future_exception(_Exception);

        _Retrieved = true;

        _Maybe_run_deferred_function(_Lock); // 可见,本函也会驱使函数的执行,以获取函数返回值

        while (!_Ready)   _Cond.wait(_Lock); // 直到函数的返回值准备好了,才返回,才会醒来

        if (_Exception)   _Rethrow_future_exception(_Exception);

        return _Result;
    }

    //******把函数的返回值存入本结构体*********

private:
    // notify waiting threads, This is virtual, but never overridden. 此是虚函数,但从没被改写过
    virtual void _Do_notify(unique_lock<mutex>* _Lock, bool _At_thread_exit)
    {
        _Has_stored_result = true; // 此数据成员显示已计算出函数返回值 , 而 _Ready 表示其它线程可以读取此返回值,分的很细。

        if (_At_thread_exit)  // notify at thread exit 要求在计算函数返回值的线程退出时,才对外显示 ready 可以读取返回值了
            _Cond._Register(*_Lock, &_Ready);  // 线程退出时还会检查 _Ready 的值,为 true 才进行唤醒操作么?? 
        else                  // notify immediately
        {
            _Ready = true;    // 反之,则是在函数返回值计算出来后立马填写 _Associated_state 的数据成员 _Ready
            _Cond.notify_all();
        }
    }

public:
    // store a (void) result while inside a locked block 对应于函数的返回值是 void 的情形
    void _Set_value_raw(unique_lock<mutex>* _Lock, bool _At_thread_exit)
    {
        if (_Has_stored_result) // 形参2  _At_thread_exit 只是为了传递给另一成函 _Do_notify(...)
            _Throw_future_error(make_error_code(future_errc::promise_already_satisfied));

        _Do_notify(_Lock, _At_thread_exit);
    }

    void _Set_value_raw(const _Ty& _Val, unique_lock<mutex>* _Lock, bool _At_thread_exit)
    {
        if (_Has_stored_result)
            _Throw_future_error(make_error_code(future_errc::promise_already_satisfied));

        _Result = _Val;                   // 函数的返回值的 copy 赋值运算符函数
        _Do_notify(_Lock, _At_thread_exit);
    }

    void _Set_value_raw(_Ty&& _Val, unique_lock<mutex>* _Lock, bool _At_thread_exit)
    {
        if (_Has_stored_result) 
            _Throw_future_error(make_error_code(future_errc::promise_already_satisfied));

        _Result = _STD forward<_Ty>(_Val); // 函数的返回值的 移动 赋值运算符函数
        _Do_notify(_Lock, _At_thread_exit);
    }

    void _Set_value(const _Ty& _Val, bool _At_thread_exit) // copy 得到的函数返回值
    {                                                       
        unique_lock<mutex> _Lock(_Mtx);
        _Set_value_raw(_Val, &_Lock, _At_thread_exit);
    }

    void _Set_value( _Ty&& _Val , bool _At_thread_exit)    // 移动 得到的函数返回值
    {                                                 
        unique_lock<mutex> _Lock(_Mtx);
        _Set_value_raw(_STD forward<_Ty>(_Val), &_Lock, _At_thread_exit);
    }

    void _Set_value(bool _At_thread_exit)   // store a (void) result
    {
        unique_lock<mutex> _Lock(_Mtx);     // 函数的返回值是 void 
        _Set_value_raw(&_Lock, _At_thread_exit);
    }

    //******以下貌似是处理异常情况,用的不多*******

    // store a result while inside a locked block
    void _Set_exception_raw(exception_ptr _Exc, unique_lock<mutex>* _Lock, bool _At_thread_exit)
    {
        if (_Has_stored_result) 
            _Throw_future_error(make_error_code(future_errc::promise_already_satisfied));

        _Exception = _Exc;  // 给本类的 _Exception 成员赋值,而不是给 _Result 成员赋值
        _Do_notify(_Lock, _At_thread_exit);
    }

    void _Set_exception(exception_ptr _Exc, bool _At_thread_exit)  // store a result
    { 
        unique_lock<mutex> _Lock(_Mtx);
        _Set_exception_raw(_Exc, &_Lock, _At_thread_exit);
    }

};

++ 接着给出对其成员函数 _Abandon ( ) 的测试

在这里插入图片描述

(17)

谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangzhangkeji

谢谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值