9

渡劫 C++ 协程(9):一个简单的示例

 2 years ago
source link: https://www.bennyhuo.com/2022/03/26/cpp-coroutines-09-http/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

渡劫 C++ 协程(9):一个简单的示例

发表于 2022-03-26 更新于 2022-03-28 阅读次数: 1 本文字数: 2.7k 阅读时长 ≈ 5 分钟

截止目前,我们一直专注于构建基于协程 API 的框架支持,这次我们用这些框架来写个简单的示例,并以此来结束整个系列的内容。

在本文当中,我将使用前文实现好的 Task 来发起一个简单的网络请求。

我会借助一些已有的框架来完成这次的目标:

cpp-httplib/0.10.4
openssl/3.0.2
nlohmann_json/3.10.5

这些框架可以通过 conan 很轻松的完成安装。

首先我们给出发起网络请求的核心代码:

// 用协程包装网络请求,请求的处理调度到 std::async 上
Task<std::string, AsyncExecutor> http_get(std::string host, std::string path) {
httplib::Client cli(host);

// 阻塞地发起网络请求
auto res = cli.Get(path.c_str());

if (res) {
// 返回响应内容,类型为 std::string
co_return res->body;
} else {
co_return httplib::to_string(res.error());
}
}

使用 httplib 来完成网络请求的处理非常简单直接,我们只需要把 url 传入即可。通常我们的网络请求都会在 io 线程当中发起,因此我们将其调度到 AsyncExecutor 上。

接下来,我们再定义一个协程来调用 http_get

Task<void, LooperExecutor> test_http() {
try {
debug("send request..."); // Looper 线程上执行

// 发起网络请求,切换线程,当前协程挂起,Looper 线程被释放(此时 Looper 线程可以去调度其他任务)
auto result = co_await http_get("https://api.github.com", "/users/bennyhuo");
// 请求返回,当前协程接着在 Looper 线程上调度执行
debug("done.");

// 业务逻辑处理,解析 json
auto json = nlohmann::json::parse(result);

// 打印 json 内容
debug(json.dump(2));
// 假装这是其他业务处理
debug(json["login"], json["url"]);
} catch (std::exception &e) {
debug(e.what());
}
}

程序运行结果如下:

22:10:54.046 [Thread-08056] (main.cpp:27) test_http: send request...
22:10:54.953 [Thread-08056] (main.cpp:29) test_http: done.
22:10:54.953 [Thread-08056] (main.cpp:31) test_http: {
"avatar_url": "https://avatars.githubusercontent.com/u/6336960?v=4",
"bio": "Google Developer Expert @Kotlin",
"blog": "https://www.bennyhuo.com",
... 中间内容很多,省略掉 ...
"updated_at": "2022-03-23T13:51:26Z",
"url": "https://api.github.com/users/bennyhuo"
}
22:10:54.953 [Thread-08056] (main.cpp:32) test_http: "bennyhuo"
22:10:54.954 [Thread-08056] (main.cpp:33) test_http: "https://api.github.com/users/bennyhuo"
22:10:54.954 [Thread-08056] (main.cpp:34) test_http: "Google Developer Expert @Kotlin"

在这个示例当中,我们没有使用协程来解决阻塞的问题,而是将一个异步的请求封装成同步的代码。test_http 当中的代码全程在 Looper 线程当中执行,尽管中间穿插了一个异步网络请求,但这看上去丝毫没有影响程序的连贯性和简洁性。

本文的内容相对轻松,因为我们终于停止了基于协程的基础 API 的探索。

实际上,如果你发现你用到的某些 API 提供了异步回调,你完全可以使用 Awaiter 对其提供 co_await 的支持。


霍丙乾 bennyhuo,Kotlin 布道师,Google 认证 Kotlin 开发专家(Kotlin GDE);《深入理解 Kotlin 协程》 作者(机械工业出版社,2020.6);前腾讯高级工程师,现就职于猿辅导


Recommend

  • 7
    • www.bennyhuo.com 2 years ago
    • Cache

    渡劫 C++ 协程(1):C++ 协程概览

    渡劫 C++ 协程(1):C++ 协程概览 发表于 2022-03-09 阅读次数: Counter not initialized! More info at console err msg. 本文字数: 7.1k 阅读时长 ≈ 13 分钟C++ 20 当中正式对协程做出了初步的支持,尽管这些 API 并不...

  • 5
    • www.bennyhuo.com 2 years ago
    • Cache

    渡劫 C++ 协程(0):前言

    渡劫 C++ 协程(0):前言 发表于 2022-03-06 更新于 2022-03-11 阅读次数: 7 本文字数: 681 阅读时长 ≈ 1 分钟C++ 20 标准发布之后,协程终于正式成为 C++ 特性当中的一员。作为一门本身极其复杂的语言,C++ 秉承着不劝退不开...

  • 10

    渡劫 C++ 协程(2):实现一个序列生成器 发表于 2022-03-11 阅读次数: 4 本文字数: 8.8k 阅读时长 ≈ 16 分钟序列生成器是一个非常经典的协程应用场景。现在我们已经了解了绝大部分 C++ 协程的特性,...

  • 3

    渡劫 C++ 协程(3):序列生成器的泛化和函数式变换 发表于 2022-03-14 阅读次数: 2 本文字数: 7.8k 阅读时长 ≈ 14 分钟我们还可以对序列生成器产生的数据流做进一步的筛选和处理,而这一切都可以基于协程去实现。

  • 10

    渡劫 C++ 协程(6):基于协程的挂起实现无阻塞的 sleep 发表于 2022-03-20 阅读次数: 本文字数: 9.4k 阅读时长 ≈ 17 分钟如果你想要等待 100ms,你会怎么做?sleep_for(100ms) 吗?在以往,我们想要...

  • 7

    渡劫 C++ 协程(4):通用异步任务 Task 发表于 2022-03-19 更新于 2022-03-20 阅读次数: 2 本文字数: 11k 阅读时长 ≈ 19 分钟协程主要用来降低异步任务的编写复杂度,异步任务各式各样,但归根结底就是一个结果的获取。

  • 14

    渡劫 C++ 协程(5):协程的调度器 发表于 2022-03-20 阅读次数: 5 本文字数: 9.4k 阅读时长 ≈ 17 分钟协程想要实现异步,很大程度上依赖于调度器的设计。调度器的抽象设计为了实现协程的异...

  • 8

    渡劫 C++ 协程(7):用于协程之间消息传递的 Channel 发表于 2022-03-22 更新于 2022-03-23 阅读次数: 本文字数: 12k 阅读时长 ≈ 23 分钟之前我们主要关注的是协程与外部调用者的交互,这次我们也关注一下对等的协程之...

  • 2
    • www.bennyhuo.com 2 years ago
    • Cache

    渡劫 C++ 协程(10):后记

    渡劫 C++ 协程(10):后记 发表于 2022-03-27 更新于 2022-03-28 阅读次数: 3 本文字数: 1.5k 阅读时长 ≈ 3 分钟渡劫 C++ 协程系列文章本来不在我的计划范围内。相较于我常用的几门语言(可能是 Kotlin、Jav...

  • 7
    • www.bennyhuo.com 2 years ago
    • Cache

    渡劫 C++ 协程(8):通用 Awaiter

    渡劫 C++ 协程(8):通用 Awaiter 发表于 2022-03-25 更新于 2022-03-28 阅读次数: 2 本文字数: 15k 阅读时长 ≈ 27 分钟每次我们新增功能时,都需要修改 TaskPromise 增加对应的 await_transform 函数,这显然是个设计问...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK