How strands guarantee the correct execution of pending events in boost.asio

Consider an echo server implemented using Boost.asio. Reading events from connected clients causes data blocks to be queued for arrival events. A thread pool works through these events - for each event, a thread takes data in the event and returns it back to the connected client.

enter image description here

As shown in the diagram above, there can be several events in the event queue from the same client. To ensure that these events for a given client are executed and delivered in order, threads are used. In this case, all events from this connected client are executed in the chain for the client.

: ? , - --, , , , - , - , ?

:

, , " ". , " "?

- , , , ?

- , , ? , ?

+4
2

strand -w390 > ; strand . strand, :

  • , ,

io_service , , . , socket " ". , :

buffer1.resize(11); // buffer is a std::vector managed elsewhere
buffer2.resize(7);  // buffer is a std::vector managed elsewhere
buffer3.resize(8);  // buffer is a std::vector managed elsewhere
socket.async_read_some(boost::asio::buffer(buffer1), handler1);
socket.async_read_some(boost::asio::buffer(buffer2), handler2);
socket.async_read_some(boost::asio::buffer(buffer3), handler3);

:

  • handler1 , buffer1 "Strawberry"
  • handler2, buffer2 ""
  • handler3, buffer3 "" .

, , . strand.


Asio Proactor [1] . . . :

socket.async_read_some(buffer, handler);

, async_read_some handler. StreamSocketService:

  • , , StreamSocketService handler io_service
  • , , Asio, . io_service, , Asio. Asio , handler io_service

io_service , , io_service, handler. .

, , . FIFO (, , ..). networking-ts, Asio, :

the buffers , . .

:

socket.async_read_some(buffer1, handler1); // op1
socket.async_read_some(buffer2, handler2); // op2

op1 op2, buffer1 , , , buffer2, handler2 handler1.

. , async_read(), , stream.async_read_some().

, async_read_some(), , async_read_some() , - async_read , :

, (, async_read, async_read_some , ), .

, - , .

, async_read() 26 :

buffer.resize(26); // buffer is a std::vector managed elsewhere
boost::asio::async_read(socket, boost::asio::buffer(buffer), handler);

"", "" , "" , async_read() socket.async_read_some(). , :

  • async_read_some() 11 , "Strawberry", , 0. 26 , async_read_some()
  • async_read_some() 7 , "" , 11. 26 , async_read_some()
  • async_read_some() 8 , "" . , 18. 26 , handler io_service

handler, buffer " ".


Strand

strand . :

  • strand s
  • f1, s s.post() s.dispatch(), s.running_in_this_thread() == false
  • f2, s s.post() s.dispatch(), s.running_in_this_thread() == false

concurrency, f1 f2 . , f1 f2, f1 f2.

auto wrapped_handler1 = strand.wrap(handler1);
auto wrapped_handler2 = strand.wrap(handler2);
socket.async_read_some(buffer1, wrapped_handler1); // op1
socket.async_read_some(buffer2, wrapped_handler2); // op2

op1 op2, buffer1 , , , buffer2, , wrapped_handler1 wrapped_handler2 . strand , :

  • handler1 handler2
  • wrapped_handler1 wrapped_handler2, handler1 handler2
  • wrapped_handler2 wrapped_handler1, handler2 handler1

, strand . strand , FIFO. , , io_service. strand FIFO, , , , io_service.

, , asio_handler_invoke() (.. strand) . question.


1. [POSA2] . ., , 2. Wiley, 2000.

+3

- , , .

( ) .

, , , , , , , .

, "", .

.

strand::post/dispatch(x);
strand::post/dispatch(y);

, x y.

x z , :

x, z, y

, io - , .

asio , .

:.

async_read(sock, mystrand.wrap([](const auto& ec, auto transferred)
{
  // this code happens in the correct strand, in the correct order.
});
+4

Source: https://habr.com/ru/post/1652163/


All Articles