24 Aralık 2017 Pazar

asio spawn metodu

Giriş
Şu satırı dahil ederiz.
#include <boost/asio/spawn.hpp>
Açıklaması şöyle. work ekler.
While spawn() adds work to the io_service (a handler that will start and jump to the coroutine), the coroutine itself is not work. To prevent the  io_service event loop from ending while a coroutine is outstanding, it may be necessary to add work to the io_service before yielding.
asenkron kodları sıralı işlemler gibi kodlayabilmeyi sağlar. Böylece bir sürü callback kodlamak zorunda kalmayız. Açıklaması şöyle.
Using coroutines has the luxury of having all coro state "implicitly" on the coro stack. This means: no more adhoc classes for async operations with state, and vastly reduced lifetime issues.
Açıklaması şöyle.
The spawn() function is a high-level wrapper over the Boost.Coroutine library. This function enables programs to implement asynchronous logic in a synchronous manner, 
spawn içinde exception atılırsa ios.run() metodunu çağıran kod içinde yakalam gerekir.

Örnek
Şöyle yaparız. İç içe iki spawn var.
boost::asio::io_service ios;

spawn(ios, [&ios](boost::asio::yield_context yield)
{
  spawn(yield, [&ios](boost::asio::yield_context yield)
  {
    boost::asio::high_resolution_timer timer{ios};
    for(unsigned i = 0; i < 3; ++i)
    {
      std::cout << i * 2 + 1 << std::endl;
      timer.expires_from_now(100ms);
       timer.async_wait(yield);
    }
  });

  spawn(yield, [&ios](boost::asio::yield_context yield)
  {
    boost::asio::high_resolution_timer timer{ios};
    for(unsigned i = 0; i < 3; ++i)
    {
      std::cout << (i + 1) * 2 << std::endl;
      timer.expires_from_now(100ms);
      timer.async_wait(yield);
    }
  });
  
});
Şöyle yaparız.
while (true) {
  try {
    ios.run();
    break;
  } catch(std::runtime_error ex) {
    std::cerr << "L:" << __LINE__ << ": " << ex.what() << "\n";
  }
}
Çıktı olarak şunu alırız.
1
2
3
4
5
6
spawn - io_service + lambda
Örnek
Parametresiz metod için şöyle yaparız.
void process()
{
  ...
}

boost::asio::io_service ios;
boost::asio::spawn(ios, [] (boost::asio::yield_context y){
  process();
});
io_service.run();
Örnek
Parametreli metod için şöyle yaparız.
void async_foo(boost::asio::io_service& io_service,
  boost::asio::yield_context& yield)
{
  ...
}

boost::asio::io_service io_service;

boost::asio::spawn(io_service, [&io_service](boost::asio::yield_context yield) {
  ...
  async_foo(io_service, yield);
  ...
});
Örnek
Elimizde bir lambda olsun.
auto go = [&](udp::endpoint ep, std::string const& m1, std::string const& m2) {
  ba::spawn(service, [=,&service](ba::yield_context yield) {
    udp::socket sock(service);
  

    auto async_message = [&](std::string const& message) {
    
      auto bytes = sock.async_send_to(ba::buffer(message), ep, yield);
    

      char read_buffer_[46];
      udp::endpoint _sender;
      bytes = sock.async_receive_from(ba::buffer(read_buffer_), _sender, yield);
    
      return std::string {read_buffer_, bytes};
    };

    try {
      sock.async_connect(ep, yield);
      

      std::cout << "Message 1 returned: '" << async_message(m1) << "'\n";
      
      ba::high_resolution_timer timer(service, delay);
      timer.async_wait(yield);

      std::cout << "Message 2 returned: '" << async_message(m2) << "'\n";

    } catch(std::exception const& e) {
      std::cout << ep << " error: " << e.what() << "\n";
    }
  });
};
Çağırmak için şöyle yaparız.
int main() {
  ba::io_service service;
  

  go({{}, 4000}, "Message01\n", "Message02\n", 3s),
  go({{}, 4001}, "Masoud\n", "Ahmad\n", 2s);

  service.run();
}
spawn - strand + lambda
İmzası şöyle
boost::asio::spawn (strand,function);
Şöyle yaparız.
boost::asio::io_service ios;
boost::asio::io_service::strand strand(ios);

boost::asio::spawn(strand, [](boost::asio::yield_context yield) {
  printf("SPAWNED\n");
});
Capturing lambda kullanmak isterse şöyle yaparız
boost::asio::io_service ios;
boost::asio::io_service::work io_work (ios);
boost::asio::io_service::strand strand (ios);

int val = 0;

boost::asio::spawn(strand, [&val](boost::asio::yield_context yield) {
  val = 3;
  });
});


Hiç yorum yok:

Yorum Gönder