|
要理解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 )
- template<typename Handler>
- int async_wait(Handler& handler)
- {
- //創建 異步流程
- boost::asio::detail::async_result_init<decltype(handler), void(int)> init(handler);
-
- //異步操作 需要傳入 init.handler 的副本
- boost::thread t([&,coro = init.handler]()
- {
- //模擬異步耗時
- boost::this_thread::sleep(ACTION_DURATION);
-
- //想 service 請求 響應
- handler.handler_.dispatcher_.dispatch(
- [&, coro = std::move(coro)]() mutable
- {
- //喚醒等待 攜程 並傳回 返回值
- coro(1);
- });
- });
-
- //讓出cpu 並等待 異步返回值
- return init.result.get();
- }
复制代码
async_result_init 的第二個模板 參數 確定了 init.result.get() 返回值型別 比如 無返回值 可以 寫作 void(void)
handler.handler_.dispatcher_ 保存了 協程 執行的 io_service
需要使用 io_service.dispatch 將 協程 喚醒 發送到 io_service 中 而不能是異步代碼的 線程中
下面是完整代碼
- #include <cstdio>
-
- #include <boost/asio.hpp>
- #include <boost/thread.hpp>
- #include <boost/bind.hpp>
- #include <boost/asio/deadline_timer.hpp>
- #include <boost/asio/spawn.hpp>
- #include <boost/smart_ptr.hpp>
-
- //使用boost的 定時器 模擬異步操作
- typedef boost::asio::deadline_timer deadline_timer_t;
- typedef boost::shared_ptr<deadline_timer_t> deadline_timer_spt;
- #define ACTION_DURATION boost::posix_time::seconds(1)
-
- //協程函數
- void coroutine(std::string name,deadline_timer_spt timer,boost::asio::yield_context ctx)
- {
- boost::system::error_code e;
- int x = 0;
-
- //step 0
- timer->expires_from_now(ACTION_DURATION);
- std::cout<<name<<"step 0 value = "<<x++<<"\n";
- timer->async_wait(ctx[e]); //yield_context 重載了 [] 用於返回 異步返回值
- if(e) //獲取返回值
- {
- std::cout<<e<<"\n";
- }
-
- //step 1
- std::cout<<name<<"step 1 value = "<<x++<<"\n";
- timer->expires_from_now(ACTION_DURATION);
- timer->async_wait(ctx[e]);
- if(e)
- {
- std::cout<<e<<"\n";
- }
-
- //step 2
- std::cout<<name<<"step 2 value = "<<x++<<"\n";
- timer->expires_from_now(ACTION_DURATION);
- timer->async_wait(ctx[e]);
- if(e)
- {
- std::cout<<e<<"\n";
- }
- }
-
-
- template<typename Handler>
- int async_wait(Handler& handler)
- {
- //創建 異步流程
- boost::asio::detail::async_result_init<decltype(handler), void(int)> init(handler);
-
- //異步操作 需要傳入 init.handler 的副本
- boost::thread t([&,coro = init.handler]()
- {
- //模擬異步耗時
- boost::this_thread::sleep(ACTION_DURATION);
-
- //想 service 請求 響應
- handler.handler_.dispatcher_.dispatch(
- [&, coro = std::move(coro)]() mutable
- {
- //喚醒等待 攜程 並傳回 返回值
- coro(1);
- });
- });
-
- //讓出cpu 並等待 異步返回值
- return init.result.get();
- }
- void coroutine(std::string name,boost::asio::yield_context ctx)
- {
- int x = 0;
- std::cout<<name<<"step 0 value = "<<x++<<"\n";
- async_wait(ctx);
-
- std::cout<<name<<"step 1 value = "<<x++<<"\n";
- async_wait(ctx);
-
- std::cout<<name<<"step 2 value = "<<x++<<"\n";
- async_wait(ctx);
-
- }
- int main(int argc, char* argv[])
- {
- boost::asio::io_service service;
-
- //啓動兩個協程 在其中模擬 異步操作
- deadline_timer_spt timer0 = boost::make_shared<deadline_timer_t>(service,ACTION_DURATION);
- deadline_timer_spt timer1 = boost::make_shared<deadline_timer_t>(service,ACTION_DURATION);
-
- //deadline_timer_spt timer = boost::make_shared<deadline_timer_t>(service,boost::posix_time::hours(1));
- // timer->async_wait([](const boost::system::error_code& e) {});
-
-
- // boost::asio::spawn(service,boost::bind(coroutine,"[one] ",timer0,_1));
- boost::asio::spawn(service,boost::bind(coroutine,"[my] ",_1));
- boost::asio::spawn(service,boost::bind(coroutine,"[two] ",timer1,_1));
-
- //運行asio服務
- service.run();
-
- return 0;
- }
复制代码
|
上一篇: boost::asio 協程下一篇: 深圳招聘mfc人才,求贤若渴
|