async(4)

Result

这里的result不是协程的返回值,后面给Task::promise_type继承

namespace ASYNCIO_NS {

/*
结果封装类
result()用于获取结果
*/

template<typename T>
struct Result {
    constexpr bool has_value() const noexcept {
        return std::get_if<std::monostate>(&result_) == nullptr;
    }
    template<typename R>
    constexpr void set_value(R&& value) noexcept {
        result_.template emplace<T>(std::forward<R>(value));
    }

    template<typename R> // for promise_type
    constexpr void return_value(R&& value) noexcept {
        return set_value(std::forward<R>(value));
    }
	
    /*
    constexpr T result() && 和  constexpr T result() & 
    这两个函数声明中的 && 和 & 符号是 cpp11 引入的“引用限定符”(reference qualifiers)。它们用于指定成员函数在对象被左值引用(&)或右值引用(&&)时的行为。
    */
    
    constexpr T result() & {
        if (auto exception = std::get_if<std::exception_ptr>(&result_)) {
            std::rethrow_exception(*exception);
        }
        if (auto res = std::get_if<T>(&result_)) {
            return *res;
        }
        throw NoResultError{};
    }
    
    constexpr T result() && {
        if (auto exception = std::get_if<std::exception_ptr>(&result_)) {
            std::rethrow_exception(*exception);
        }
        if (auto res = std::get_if<T>(&result_)) {
            return std::move(*res);
        }
        throw NoResultError{};
    }

    void set_exception(std::exception_ptr exception) noexcept { result_ = exception; }
    void unhandled_exception() noexcept { result_ = std::current_exception(); }

private:
    // std::variant 用于表示可以包含多种类型中的一个的值。它类似于联合体(union)但提供类型安全和额外功能
    // reuslt_有三种值:
    // T
    // std::monostate: 表示一个空状态或者占位符时
    // std::exception_ptr 一个指向异常对象的指针,允许在异常被捕获后将异常对象保存起来,以便稍后重新抛出
    std::variant<std::monostate, T, std::exception_ptr> result_;
};

// 特化
template<>
struct Result<void> {
    constexpr bool has_value() const noexcept {
        return result_.has_value();
    }
    void return_void() noexcept {
        result_.emplace(nullptr);
    }
    void result() {
        if (result_.has_value() && *result_ != nullptr) { std::rethrow_exception(*result_); }
    }

    void set_exception(std::exception_ptr exception) noexcept { result_ = exception; }
    void unhandled_exception() noexcept { result_ = std::current_exception(); }

private:
    std::optional<std::exception_ptr> result_;
};

}

Task

这里的Task有两个用处:

  1. 作为协程的返回值
  2. 给ScheduledTask用

根据Future的定义,因为Task有get_result(),有promise_type,支持移动构造,不支持默认构造。所以Task就是一个Future

Task::promise_type,注意到这里继承了两个类:std::coroutine_handle<promise_type> 和 Result 。 证明promise_type也是一个协程句柄,可以调度,且可以获取结果。

std::coroutine_handle<promise_type>注意以下几个成员函数:

done(): 检查协程是否已完成

resume(): 恢复协程执行

destroy(): 销毁协程

promise(): 访问协程的承诺对象

	struct InitialSuspendAwaiter { // 专门用于initial_suspend()
        constexpr bool await_ready() const noexcept { return !wait_at_initial_suspend_; }

        constexpr void await_suspend(std::coroutine_handle<>) const noexcept {}

        constexpr void await_resume() const noexcept {}

        const bool wait_at_initial_suspend_{true};
    };

	struct FinalAwaiter { // 专门用于final_suspend()
        constexpr bool await_ready() const noexcept { return false; } // 要挂起

        template<typename Promise>
        constexpr void await_suspend(std::coroutine_handle<Promise> h) const noexcept {
            if (auto cont = h.promise().continuation_) { // continuation_代表什么???
                get_event_loop().call_soon(*cont);
            }
        }

        constexpr void await_resume() const noexcept {}
    };

	// 这里继承了两个类:std::coroutine_handle<promise_type> 和  Result<R>
    struct promise_type: CoroHandle, Result<R> {
        
        // 下面三个都是构造函数
        promise_type() = default;

        template<typename... Args> // from free function
        promise_type(NoWaitAtInitialSuspend, Args&&...): wait_at_initial_suspend_{false} { }
        
        template<typename Obj, typename... Args> // from member function
        promise_type(Obj&&, NoWaitAtInitialSuspend, Args&&...): wait_at_initial_suspend_{false} { }

        auto initial_suspend() noexcept {
            return InitialSuspendAwaiter{wait_at_initial_suspend_};
        }
        
        auto final_suspend() noexcept {
            return FinalAwaiter {};
        }
        
        Task get_return_object() noexcept {
            return Task{coro_handle::from_promise(*this)};
        }

        ///
        void run() final { // 实现CoroHandle::run() (Handle::run())
            coro_handle::from_promise(*this).resume();
        }
        
        const std::source_location& get_frame_info() const final { return frame_info_; }
        
        void dump_backtrace(size_t depth = 0) const final {
            fmt::print("[{}] {}\n", depth, frame_name());
            if (continuation_) { continuation_->dump_backtrace(depth + 1); }
            else { fmt::print("\n"); }
        }
        ///
		// 成员变量:
        const bool wait_at_initial_suspend_ {true}; // 是否在协程初始化时挂起
        CoroHandle* continuation_ {};				// ???????????
        std::source_location frame_info_{};			// 源码信息(调试用)
    };

Task:AwaiterBase

struct AwaiterBase {
    constexpr bool await_ready() {
        if (self_coro_) [[likely]]   	// 如果句柄不为空,根据done()返回结果,done就不用挂起了,否则需要挂起
        { return self_coro_.done(); }	
        return true;					// 句柄为空直接返回true,不用挂起
    }

    template<typename Promise>
    void await_suspend(std::coroutine_handle<Promise> resumer) const noexcept {
        assert(! self_coro_.promise().continuation_); 	// continuation_为空
        resumer.promise().set_state(Handle::SUSPEND);	// 将resumer的状态设置为suspend
        self_coro_.promise().continuation_ = &resumer.promise(); // 将Task的handle_的promise的continuation_设置为当前协程的promise

        self_coro_.promise().schedule();						// 将Task的handle_加入调度
    }

    // 少了一个await_resume()

    coro_handle self_coro_ {}; // using coro_handle = std::coroutine_handle<promise_type>;
    							// 这个是Task的handle_
};
namespace ASYNCIO_NS {
    
struct NoWaitAtInitialSuspend {};
// 使用了 inline 和 constexpr 关键字。这样定义的变量在每个编译单元中都是唯一的,且可以在编译时计算出其值,使得它在编译时就能被完全初始化。
inline constexpr NoWaitAtInitialSuspend no_wait_at_initial_suspend;

    
template<typename R = void>
struct Task: private NonCopyable {
    struct promise_type;
    
    // std::coroutine_handle<> 是 cpp20 标准引入的一个类型,用于表示一个协程的句柄。它是一种轻量级的对象,可以用来恢复、暂停和销毁协程。它的模板参数代表协程的 promise 类型。
    using coro_handle = std::coroutine_handle<promise_type>;

    template<concepts::Future>
    friend struct ScheduledTask;
	
    
    // 构造函数
    explicit Task(coro_handle h) noexcept: handle_(h) {}
    
    // 移动构造函数
    Task(Task&& t) noexcept
        : handle_(std::exchange(t.handle_, {})) {}  // std::exchange提供了一种原子操作,用于交换给定对象的值,并返回该对象原始的值。这个函数的作用类似于 std::swap,但它不会创建临时对象,因此更适用于某些情况下的性能优化

    ~Task() { destroy(); }
	
    
    // 返回结果,从promise.result()返回
    decltype(auto) get_result() & {
        return handle_.promise().result();
    }

    decltype(auto) get_result() && {
        return std::move(handle_.promise()).result();
    }
   
    
    /*
    使得Task能跟在co_await表达式后面,即co_await Task
    */
    auto operator co_await() const & noexcept {
        struct Awaiter: AwaiterBase {
            decltype(auto) await_resume() const {
                if (! AwaiterBase::self_coro_) [[unlikely]]
                { throw InvalidFuture{}; }
                return AwaiterBase::self_coro_.promise().result(); // Task::promise_type继承Result,所以有result()函数
            }
        };
        return Awaiter {handle_};
    }
	
    auto operator co_await() const && noexcept {
        struct Awaiter: AwaiterBase {
            decltype(auto) await_resume() const {
                if (! AwaiterBase::self_coro_) [[unlikely]]
                { throw InvalidFuture{}; }
                return std::move(AwaiterBase::self_coro_.promise()).result();
            }
        };
        return Awaiter {handle_};
    }     
    

    bool valid() const { return handle_ != nullptr; }
    
    bool done() const { return handle_.done(); }
private:
    void destroy() {
        if (auto handle = std::exchange(handle_, nullptr)) {
            handle.promise().cancel(); 	// handle取消调度(CoroHandle::cancel())
            handle.destroy();			// std::coroutine_handle<promise_type>::destroy()
        }
    }
private:
    coro_handle handle_; // using coro_handle = std::coroutine_handle<promise_type>; Task所在协程的协程句柄
};

static_assert(concepts::Promise<Task<>::promise_type>);
static_assert(concepts::Future<Task<>>);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/575447.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

查看HDF5文件软件(HDFView)

HDFView&#xff1a;下载地址 note&#xff1a;我们需要下载 win10 、App软件&#xff08;win10在win11也能运行&#xff09;&#xff0c;因为App软件是轻量版&#xff0c;不需要安装就可以使用。 eg&#xff1a; 下载完后解压就可以使用。

空间数据索引的利器:R-Tree原理与实现深度解析

空间数据索引的利器&#xff1a;R-Tree原理与实现深度解析 R-Tree的原理插入操作分裂操作查询操作 R-Tree的伪代码R-Tree的C语言实现讨论结论 R-Tree是一种平衡树&#xff0c;用于空间数据索引&#xff0c;特别是在二维或更高维度的几何对象存储和检索中。它由Antony Guttman和…

书生·浦语 大模型(学习笔记-9)OpenCompass 大模型评测实战

目录 一、评测实现双赢 二、评测遇到的问题 三、如何评测大模型&#xff08;大概总结4大类方法&#xff09; 四、评测工具链及流水线 五、实战评测 GPU的环境安装 查看支持的数据集和模型 启动评测(会缺少protibuf库&#xff0c;提前安装&#xff09; 测评结果 一、评…

【蓝桥2025备赛】容斥原理

容斥原理 背景&#xff1a;两个集合相交 高中的韦恩图&#xff0c;我们知道两个集合相交时我们可以通过简单的计算来认识相关的性质 集合相交的区域是 A ∩ B A\cap B A∩B ,集合的并集是 A ∪ B A\cup B A∪B ,那怎么用集合表示 A ∪ B A\cup B A∪B 我们可以看作是A集合…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-6.3

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

mybatis的使用技巧9——mysql按年、季度、月、周等不同时间维度查询或分组统计

在实际项目开发过程中&#xff0c;按不同时间维度查询业务数据的操作异常频繁。比较多的操作如支持按时间周期范围做列表数据的筛选&#xff0c;或者是按年月日等维度的图表展示&#xff0c;亦或者是首页的概况&#xff0c;三维大屏的展示等&#xff0c;都离不开不同时间周期查…

网络靶场实战-Qiling Fuzz实例分析

背景 在上一小节中&#xff0c;介绍了qiling框架的背景和基础使用&#xff0c;并以相关的CTF和qilinglab实例进行练习加深对qiling框架的使用&#xff0c;后续并简单介绍了qiling fuzz的功能。 在这一小节&#xff0c;我们将对qiling fuzz iot设备进行测试以及以实例的方式对…

中级信息系统管理工程师-必会题锦集

文章目录 中级信息系统管理工程师-必会题锦集题目一CPU[解析]试题二 CPU[解析] 中级信息系统管理工程师-必会题锦集 题目一CPU CPU中&#xff08;1&#xff09;不仅要保证指令的正确执行&#xff0c;还要能够处理异常事件。 A. 运算器 B. 控制器 C. 寄存器组 D. 内部总线 [解…

1.C++入门(上)

目录 1.C关键字 2.命名空间 作用域方面的优化 a.命名空间定义 b.命名空间使用 3.C 输入&输出 1.C关键字 C有63个关键字&#xff0c;C语言有32个关键字&#xff0c;存在重叠如荧光笔标出 2.命名空间 作用域方面的优化 如果变量&#xff0c;函数和类的名称都存在于全…

SpringBootWeb请求

文章目录 前言一、Postman介绍 二、简单参数三、实体参数四、数组集合参数五、日期参数六、JSON参数七、路径参数 前言 在上一篇文章中&#xff0c;已经基于SpringBoot的方式开发一个web应用&#xff0c;浏览器发起请求 /hello 后 &#xff0c;给浏览器返回字符串 “Hello Wor…

C++笔试强训day7

目录 1.字符串中找出连续最长的数字串 2.岛屿数量 3.拼三角 1.字符串中找出连续最长的数字串 链接 我的思路很简洁&#xff0c;就是双指针遍历&#xff0c;然后不断更新左位置left和右位置right和长度len。 然后我写代码的时候代码思路没跟上原本思路&#xff0c;直接把所有…

遇坑分享24.4.25

在对数组进行排序算法时&#xff0c;如果我使用多个下标进行元素交换的时候&#xff0c;可能会出错。 以下面的直接选择排序&#xff08;排列升序&#xff09;为例&#xff1a; public static void selectSort1(int[] arr){int left0;int rightarr.length-1;while(left<rig…

2024HWqax线上产品培训试题(天眼)

最近做了qax笔试题&#xff0c;分享一下&#xff0c;仅供学习参考&#xff0c;侵删

力扣HOT100 - 200. 岛屿数量

解题思路&#xff1a; 岛屿题目一般使用dfs。 1.判断是否越界 2.用0&#xff0c;1&#xff0c;2三个状态标识当前格子的状态&#xff08;三个状态比两个状态更清晰&#xff09; 3.向周围四个方向遍历 class Solution {public int numIslands(char[][] grid) {int cnt 0;fo…

【Spring篇 | 补充】三级缓存解决循环依赖

文章目录 7.三级缓存解决循环依赖7.1何为循环依赖&#xff1f;7.2三级缓存解析7.3三级缓存解决循环依赖7.3.1实例化A7.3.2创建B的需求7.3.3实例化B7.3.4注入A到B7.3.5B创建完成7.3.6回溯至A7.3.7清理二级缓存 7.4为什么不能用二级缓存解决循环依赖&#xff1f; 7.三级缓存解决循…

删除docker的容器与镜像

如果您想要卸载通过 docker pull influxdb 命令下载的 InfluxDB 容器&#xff0c;您需要执行以下步骤&#xff1a; 1. **停止正在运行的 InfluxDB 容器**&#xff1a; 首先&#xff0c;您需要停止任何正在运行的 InfluxDB 容器。您可以使用以下命令来查找正在运行的 InfluxD…

Xilinx 7系列 clock IP核的使用(二)

在 Clocking Wizard 中的输出时钟设置部分&#xff0c;主要目的是生成并配置系统所需的特定时钟频率和信号。这一功能在硬件设计和开发中非常关键&#xff0c;因为它允许用户精确地控制各个部分的时钟信号&#xff0c;以满足特定的性能、功耗和时序要求。 1 配置输出时钟 要启…

宝宝洗衣机买什么样的好?诚意推荐四款实力超群的婴儿洗衣机

近几年家用洗衣机标准容积的大大增加&#xff0c;从5Kg、6Kg升级到9Kg、10Kg。大容量洗衣机满足了家庭中清洗大件衣物、床上用品的需求。但由于普通大型洗衣机所洗衣物混杂&#xff0c;很多时候由于宝宝小件衣物数量不多&#xff0c;却也并不适合放在一起扔进大型洗衣机中清洗。…

macOS 一些系统图标的存放位置 icns

macOS 一些系统图标的存放位置 icns macOS 中有很多好看的图标&#xff0c;有时候就想用一下它&#xff0c;我来告诉你他们的具体位置。 系统图标位置&#xff0c;像各种通用文件类型的图标都在这里面&#xff0c;里面好多高清的系统图标 /System/Library/CoreServices/Core…

使用PlantUML绘制活动图、泳道图

最近在学PlantUML 太漂亮了 给大家欣赏一下 我也记录一下 startuml |使用前| start :用户打开旅游App; |#LightSkyBlue|使用后| :用户浏览旅游信息; |#AntiqueWhite|登机前| :用户办理登机手续; :系统生成登机牌; |使用前| :用户到达机场; |登机前| :用户通过安检; |#Light…
最新文章