25 Ocak 2018 Perşembe

asio strand Sınıfı

Giriş
Şu satırı dahil ederiz.
#include <boost/asio.hpp>
Açıklaması şöyle
The io_service::strand class provides the ability to post and dispatch handlers with the guarantee that none of those handlers will execute concurrently
Bir kod bloğunun tek bir thread tarafından çalıştırılmasını sağlar. Stranda aslında bir kuyruktan ibarettir.  Örneğin bir kuyruktan mesaj çekme işlemi asio tarafından çalıştırılıyorsa, mutex ile koruma yerine strand kullanılır.

Asio işlemi iptal olsa bile callback  operation_aborted bayrağı ile yine strand tarafından çalıştırılır.

Farklı strand nesnelerinin hangi thread tarafından çalıştırılacağı ve çalışma sırası belirsizdir. Açıklaması şöyle
The implementation makes no guarantee that handlers posted or dispatched through different strand objects will be invoked concurrently.
Strand sayısı kısıtlıdır. Varsayılan sayı 193'tür. Açıklaması şöyle
Made the number of strand implementations configurable by defining BOOST_ASIO_STRAND_IMPLEMENTATIONS to the desired number.
Tanımlama
Yeni asio ile şöyle yaparız.
boost::asio::strand<boost::asio::io_context::executor_type> strand;
Constructor
Strand sınıfı da diğer tüm asio sınıfları gibi bir io_service ile ilklendirilir.
boost::asio::io_service::strand strand (ios );
dispatch metodu
Örnek ver Şöyle yaparız.
int value = 0;

// handler is immediately executed.
auto handler3 = [&value]() { value = 3; };
strand.dispatch(handler3);
get_io_service metodu
Şöyle yaparız.
asio::ip::tcp::socket socket {strand.get_io_service()};
post metodu
io_service post metodu yerine strand'in post metodu kullanılır. Şöyle yaparız.
strand.post (boost::bind( &PrintNum, 1 ) );
İstenirse lambda kullanılabilir. Şöyle yaparız.
int val = 0;

strand.post([&val]() {
  val = 1;
  ...
});
running_in_this_thread metodu
Şöyle yaparız.
boost::asio::io_service::strand strand (ios);

auto handler = [&strand1]() {
  assert(strand1.running_in_this_thread());
  ...
};
wrap metodu
İki tane async işlem sonucu strand ile wrap edillirse, hangisinin önce çağrılacağı belirsiz. Açıklaması şöyle
Note that in the following case:
async_op_1(..., s.wrap(a));
async_op_2(..., s.wrap(b)); 
the completion of the first async operation will perform s.dispatch(a), and the second will perform s.dispatch(b), but the order in which those are performed is unspecified. That is, you cannot state whether one happens-before the other. Therefore none of the above conditions are met and no ordering guarantee is made.
Şöyle yaparız.
void connection::async_write(...)
{
  ...
  // `strand_` protects `message_queue_` and guarantees that writes to
  // `socket_` are only occurring within the strand.
  strand_.post([...]()
    {
      auto empty = message_queue_.empty();
      message_queue_.push([=]()
        {
          ...
          // Intermediate and final handlers are performed within `strand_`.
          boost::asio::async_write(socket_, ... strand_.wrap([...](...)
            {
              ...
              message_queue_.front()()
            }));
        });
      if (empty)
        message_queue_.front()();
    });
}
Şöyle yaparız.
struct connection
    : std::enable_shared_from_this<connection>
{
    

  void run()
  {
    asio::async_read_until(socket_, buffer_, "\n",
      strand_.wrap([self = shared_from_this()](auto const&ec, auto size)
      {
        if (size == 0 )
        {
          // error condition
          boost::system::error_code sink;
          self->socket_.shutdown(asio::ip::tcp::socket::shutdown_receive, sink);
        }
        else {
          ...
          self->run();
        }
      })
    );
  }
...
}




Hiç yorum yok:

Yorum Gönder