2014-09-30 58 views
3

當使用Boost.Asio堆棧式協同程序時,如何「手動」產出以便另一個協同程序或異步操作有機會運行?例如,我需要發送給我從TCP套接字接收命令的響應之前執行長時間的計算:在Boost.Asio中產生Stackful Coroutine

asio::spawn(strand_, [this, self](asio::yield_context yield) 
{ 
    char data[256]; 
    while (socket_.is_open()) 
    { 
     size_t n = socket_.async_read_some(boost::asio::buffer(data), 
              yield); 

     if (startsWith(data, "computePi")) 
     { 
      while (!computationFinished) 
      { 
       computeSomeMore(); 
       yield; // WHAT SHOULD THIS LINE BE? 
      } 

      storeResultIn(data); 
      boost::asio::async_write(socket_, boost::asio::buffer(data, n), 
            yield); 
     } 
    } 
}); 

回答

4

這是簡單的比你想象的:

iosvc.post(yield); 

會做的伎倆。

iosvc從@ sehe的示例代碼借用)

+0

這確實看起來更乾淨。 – sehe 2014-10-05 18:06:23

4

你可以只調用poll_one()在io_service對象上。

全部工作示例:

#include <boost/asio.hpp> 
#include <boost/asio/spawn.hpp> 
#include <boost/algorithm/string/predicate.hpp> 
#include <boost/thread.hpp> 
#include <iostream> 

namespace asio = boost::asio; 
using boost::asio::ip::tcp; 
using std::begin; 
using std::end; 

bool computationFinished = false; 
void computeSomeMore() { 
    static int count = 0; 
    if (count++>10) 
    { 
     computationFinished = true; 
     std::cout << "Calculation finished\n"; 
    } else 
    { 
     std::cout << "Calculating...\n"; 
     boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); 
    } 
} 

template <typename T> void storeResultIn(T& a) { 
    std::fill(begin(a), end(a), '4'); 
} 

int main() 
{ 
    asio::io_service iosvc; 
    tcp::socket s(iosvc); 
    tcp::resolver r(iosvc); 

    tcp::acceptor a(iosvc, tcp::endpoint(tcp::v4(), 6767)); 

    a.accept(s); 
    { 
     asio::spawn(iosvc, [&iosvc,&s](asio::yield_context yield) 
     { 
      char data[256]; 
      while (s.is_open()) 
      { 
       size_t n = s.async_read_some(boost::asio::buffer(data), yield); 

       if (boost::algorithm::starts_with(data, "computePi")) 
       { 
        iosvc.post([]{std::cout << "I can still breath\n";}); // some demo work 
        iosvc.post([]{std::cout << "And be responsive\n";}); 

        while (!computationFinished) 
        { 
         computeSomeMore(); 
         iosvc.poll_one(); // this enables the demo work to be run 
        } 

        storeResultIn(data); 
        boost::asio::async_write(s, boost::asio::buffer(data, n), yield); 
       } else 
       { 
        std::cout << "Received unknown command '" << std::string(data, data+n) << "'\n"; 
       } 
      } 
     }); 
    } 

    iosvc.run(); 
    std::cout << "Bye bye\n"; 
} 

當發送 「computePi」,服務器打印:

Calculating... 
I can still breath 
Calculating... 
And be responsive 
Calculating... 
Calculating... 
Calculating... 
Calculating... 
Calculating... 
Calculating... 
Calculating... 
Calculating... 
Calculating... 
Calculation finished 
+0

新增工作示例 – sehe 2014-09-30 21:50:47

+0

我喜歡你怎麼把我的'startsWith'和'storeResultIn'僞到實際工作的代碼! – 2014-09-30 22:14:21

+3

這是[不可或缺的技能](http://kera.name/articles/2013/10/nobody-writes-testcases-any-more/)。我需要自己在可能的情況下測試我的答案。這是一項很棒的運動,而且很有趣。 – sehe 2014-09-30 22:21:09