VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 1107|回复: 0

[交流] 適配異步代碼到 asio 協程

[复制链接]
74_avatar_middle
在线会员 发表于 2017-5-30 11:16:19 | 显示全部楼层 |阅读模式
要理解asio的內部實現 非一日之功 孤亦不能完全掌握 且孤以爲 僅需知道其大概原理 之後 瞭解如何靈活使用即可
(這樣節省下的 許多時間 就可以做更多有意義的事 比如 聽一整天 阿梅 mui 的音樂)

要適配 異步到 asio 異常簡單 僅需要按部就班的 執行如下操作
1  創建一個 接受 boost::asio::yield_context& 參數的函數
2 在 函數中 使用 yield_context 創建一個 boost::asio::detail::async_result_init 型別 init
3 創建 init.handler 副本 coro
4 調用 異步代碼 在異步完成時 通過 調用 coro() 通知asio 喚醒協程
5 執行 return init.result.get(); 讓出cpu 並且等待 被喚醒時 返回 返回值

example 自定義了一個類似 asio::deadline_timer 的 async_wait 示例
(代碼儘量 保存簡介 以避免被 asio更多的 宏 模板 干擾 理解
如果是項目代碼 可能需要 修改 比如 像 asio一樣 返回值 型別 由調用傳入的yield_context 確認 而非此處固定爲 int )
  1. template<typename Handler>
  2. int async_wait(Handler& handler)
  3. {
  4.     //創建 異步流程
  5.     boost::asio::detail::async_result_init<decltype(handler), void(int)> init(handler);

  6.     //異步操作 需要傳入 init.handler 的副本
  7.     boost::thread t([&,coro = init.handler]()
  8.     {
  9.         //模擬異步耗時
  10.         boost::this_thread::sleep(ACTION_DURATION);

  11.         //想 service 請求 響應
  12.         handler.handler_.dispatcher_.dispatch(
  13.             [&, coro = std::move(coro)]() mutable
  14.         {
  15.             //喚醒等待 攜程 並傳回 返回值
  16.             coro(1);
  17.         });
  18.     });

  19.     //讓出cpu 並等待 異步返回值
  20.     return init.result.get();
  21. }
复制代码

async_result_init 的第二個模板 參數 確定了 init.result.get() 返回值型別 比如 無返回值 可以 寫作 void(void)
handler.handler_.dispatcher_ 保存了 協程 執行的 io_service
需要使用 io_service.dispatch 將 協程 喚醒 發送到 io_service 中 而不能是異步代碼的 線程中


下面是完整代碼
  1. #include <cstdio>

  2. #include <boost/asio.hpp>
  3. #include <boost/thread.hpp>
  4. #include <boost/bind.hpp>
  5. #include <boost/asio/deadline_timer.hpp>
  6. #include <boost/asio/spawn.hpp>
  7. #include <boost/smart_ptr.hpp>

  8. //使用boost的 定時器 模擬異步操作
  9. typedef boost::asio::deadline_timer deadline_timer_t;
  10. typedef boost::shared_ptr<deadline_timer_t> deadline_timer_spt;
  11. #define ACTION_DURATION boost::posix_time::seconds(1)

  12. //協程函數
  13. void coroutine(std::string name,deadline_timer_spt timer,boost::asio::yield_context ctx)
  14. {
  15.     boost::system::error_code e;
  16.     int x = 0;

  17.     //step 0
  18.     timer->expires_from_now(ACTION_DURATION);
  19.     std::cout<<name<<"step 0 value = "<<x++<<"\n";
  20.     timer->async_wait(ctx[e]); //yield_context 重載了 [] 用於返回 異步返回值
  21.     if(e) //獲取返回值
  22.     {
  23.         std::cout<<e<<"\n";
  24.     }

  25.     //step 1
  26.     std::cout<<name<<"step 1 value = "<<x++<<"\n";
  27.     timer->expires_from_now(ACTION_DURATION);
  28.     timer->async_wait(ctx[e]);
  29.     if(e)
  30.     {
  31.         std::cout<<e<<"\n";
  32.     }

  33.     //step 2
  34.     std::cout<<name<<"step 2 value = "<<x++<<"\n";
  35.     timer->expires_from_now(ACTION_DURATION);
  36.     timer->async_wait(ctx[e]);
  37.     if(e)
  38.     {
  39.         std::cout<<e<<"\n";
  40.     }
  41. }


  42. template<typename Handler>
  43. int async_wait(Handler& handler)
  44. {
  45.     //創建 異步流程
  46.     boost::asio::detail::async_result_init<decltype(handler), void(int)> init(handler);

  47.     //異步操作 需要傳入 init.handler 的副本
  48.     boost::thread t([&,coro = init.handler]()
  49.     {
  50.         //模擬異步耗時
  51.         boost::this_thread::sleep(ACTION_DURATION);

  52.         //想 service 請求 響應
  53.         handler.handler_.dispatcher_.dispatch(
  54.             [&, coro = std::move(coro)]() mutable
  55.         {
  56.             //喚醒等待 攜程 並傳回 返回值
  57.             coro(1);
  58.         });
  59.     });

  60.     //讓出cpu 並等待 異步返回值
  61.     return init.result.get();
  62. }
  63. void coroutine(std::string name,boost::asio::yield_context ctx)
  64. {
  65.     int x = 0;
  66.     std::cout<<name<<"step 0 value = "<<x++<<"\n";
  67.     async_wait(ctx);

  68.     std::cout<<name<<"step 1 value = "<<x++<<"\n";
  69.     async_wait(ctx);

  70.     std::cout<<name<<"step 2 value = "<<x++<<"\n";
  71.     async_wait(ctx);

  72. }
  73. int main(int argc, char* argv[])
  74. {
  75.     boost::asio::io_service service;

  76.     //啓動兩個協程 在其中模擬 異步操作
  77.     deadline_timer_spt timer0 = boost::make_shared<deadline_timer_t>(service,ACTION_DURATION);
  78.     deadline_timer_spt timer1 = boost::make_shared<deadline_timer_t>(service,ACTION_DURATION);

  79.     //deadline_timer_spt timer = boost::make_shared<deadline_timer_t>(service,boost::posix_time::hours(1));
  80.     // timer->async_wait([](const boost::system::error_code& e) {});


  81.     //  boost::asio::spawn(service,boost::bind(coroutine,"[one] ",timer0,_1));
  82.     boost::asio::spawn(service,boost::bind(coroutine,"[my] ",_1));
  83.     boost::asio::spawn(service,boost::bind(coroutine,"[two] ",timer1,_1));

  84.     //運行asio服務
  85.     service.run();

  86.     return 0;
  87. }
复制代码





上一篇:boost::asio 協程
下一篇:深圳招聘mfc人才,求贤若渴
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2019-9-19 00:30

Powered by Discuz! X3.4

© 2009-2019 cctry.com

快速回复 返回顶部 返回列表