Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /////////////////////////////////
- // 程序一:以协程包装阻塞的库中的功能
- /////////////////////////////////
- using namespace std::chrono_literals;
- namespace coro = concurrencpp;
- namespace MyAPI {
- class Api {
- private:
- coro::runtime& runtime;
- std::shared_ptr<coro::executor> mainThreadExecutor;
- std::shared_ptr<coro::thread_pool_executor> workerExecutor; // Thread pool executor
- public:
- Api(coro::runtime &runtime,
- std::shared_ptr<coro::executor> mainThreadExecutor
- ) :
- runtime{ runtime },
- mainThreadExecutor{ std::move(mainThreadExecutor) },
- workerExecutor{ runtime.thread_pool_executor() } { }
- // 调 HTTP 接口
- coro::result<std::string> callHttpApi() {
- // 1. 切换到后台线程池执行耗时操作
- co_await coro::resume_on(workerExecutor);
- // 醒來,已處於 workerExecutor
- std::this_thread::sleep_for(1s); // 模拟耗时网络请求
- // 2. 操作完成,切换回主线程
- co_await coro::resume_on(mainThreadExecutor);
- // 醒來,已處於 mainThreadExecutor
- co_return "asdf";
- }
- };
- } // namespace MyAPI
- bool btnClicked() {
- static int frame = 0;
- frame++;
- // 模擬第四幀按下按鈕
- return frame == 4;
- }
- void drawUi() {
- std::println("draw ui");
- std::this_thread::sleep_for(0.3s);
- }
- int main() {
- coro::runtime runtime;
- auto mainThreadExecutor = runtime.make_manual_executor();
- // --- 实例化 MyAPI::Api ---
- MyAPI::Api myApi{ runtime, mainThreadExecutor };
- while (true) {
- if (btnClicked()) {
- [&]() -> coro::result<void> {
- std::cout << "onBtn started on thread: " << std::this_thread::get_id() << std::endl;
- std::println("耗时任务执行始");
- co_await myApi.callHttpApi();
- std::cout << "onBtn resumed on thread: " << std::this_thread::get_id() << std::endl;
- std::println("耗时任务执行终");
- }();
- }
- mainThreadExecutor->loop_once();
- drawUi();
- }
- return 0;
- }
- /*
- 程序一的输出如下:
- draw ui
- draw ui
- draw ui
- onBtn started on thread: 12628
- 耗时任务执行始
- draw ui
- draw ui
- draw ui
- draw ui
- onBtn resumed on thread: 12628
- 耗时任务执行终
- draw ui
- draw ui
- draw ui
- */
- /////////////////////////////////
- // 程序二:Promise 的运用
- /////////////////////////////////
- using namespace std::chrono_literals;
- namespace coro = concurrencpp;
- namespace MyAPI {
- struct BackendMsg
- {
- std::string id;
- std::string data;
- };
- class Api {
- public:
- std::unordered_map<std::string, coro::result_promise<std::string>> reqId2Promise;
- // 当收到 websockets 消息时,调用此函数
- void onRecvBackendMsg(BackendMsg msg) {
- if (auto it = reqId2Promise.find(msg.id); it != reqId2Promise.end()) {
- it->second.set_result(msg.data);
- }
- }
- // websockets 发一个信息,并等待这个信息的回复
- coro::result<std::string> sendReqAndWaitForResp(BackendMsg msg) {
- std::println("已发送 ID 为 {} 的消息,正等待回应……", msg.id);
- auto& promise = reqId2Promise[msg.id];
- // sendMsgToBackend(msg);
- std::string resp = co_await promise.get_result();
- std::println("回应:{}", resp);
- co_return resp;
- }
- };
- } // namespace MyAPI
- bool btn1Clicked() {
- static int frame = 0;
- frame++;
- // 模擬第四幀按下按鈕
- return frame == 4;
- }
- bool btn2Clicked() {
- static int frame = 0;
- frame++;
- // 模擬第六幀按下按鈕
- return frame == 6;
- }
- void drawUi() {
- std::println("draw ui");
- std::this_thread::sleep_for(0.3s);
- }
- int main() {
- MyAPI::Api myApi;
- while (true) {
- if (btn1Clicked()) {
- [&]() -> coro::result<void> {
- std::string resp = co_await myApi.sendReqAndWaitForResp({ "test-msg-1", "PING!" });
- std::println("收到回应{}!", resp);
- }();
- }
- if (btn2Clicked()) {
- myApi.onRecvBackendMsg({ "test-msg-1", "PONG!" });
- }
- drawUi();
- }
- return 0;
- }
- /*
- 程序二的输出如下:
- draw ui
- draw ui
- draw ui
- 已发送 ID 为 test-msg-1 的消息,正等待回应……
- draw ui
- draw ui
- 回应:PONG!
- 收到回应PONG!!
- draw ui
- draw ui
- draw ui
- ……
- */
Advertisement
Add Comment
Please, Sign In to add comment