Boost logo

Boost Users :

Subject: Re: [Boost-users] [asio] Does ssl::stream allow multiple pending async operations?
From: Vinnie Falco (vinnie.falco_at_[hidden])
Date: 2017-11-05 14:46:31


On Sun, Nov 5, 2017 at 6:00 AM, Phil Sean via Boost-users
<boost-users_at_[hidden]> wrote:
> Does this mean we have to wait for an async operation to finish before another is started (for read/read, read/write, and write/write)?

I believe you can have one outstanding read and one outstanding write
operation pending simultaneously for ssl::stream and tcp::socket.

> (Async operations refer to async_read_some() and async_write_some(), not the composed operations.)

All calls to initiating functions (functions prefixed with "async_")
are considered asynchronous operations, composed or otherwise.

> If so, is the operation said to have finished when the handler is invoked or when the handler returns?

The operation is finished when the handler is invoked.

> If not, what's the difference between the async operations of ip::tcp::socket and ssl::stream

tcp::socket transfers buffers unmodified, while ssl::stream encrypts
data both ways and supports other cryptographic operations such as
providing certificates during handshakes.

> I came across different views on this problem. This answer[1] suggests that simply using the same strand (ie. no concurrency) will suffice. Another one[2] says multiple pending asynchronous operations can be problematic for ssl::stream even if no concurrency occurs.

It is very easy to mix up "thread safety" with "multiple pending
asynchronous operations".

The Thread Safety clause (Shared Objects: unsafe) is very specific. It
means that no member functions may be invoked concurrently. That is to
say:

* No async_read from two threads at the same time
* No async_write from two threads at the same time
* No cancel or close while also calling async_* from multiple threads
concurrently

The last point is especially important. According to the Asio
documentation, you cannot close a socket from another thread while
asynchronous operations are pending. You must post a function to the
implicit or explicit strand which closes the socket.

This should not be confused with "multiple pending operations." For
example, you can call async_read followed by async_write (from the
correct implicit or explicit strand), without waiting for any
completions. There is only one thread in this scenario.

Note the careful wording of "implicit or explicit strand." This means:

* implicit strand: Only one thread calling io_service::run
* explicit strand: Completion handlers are wrapped using
io_service::strand::wrap

I hope this helps!


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net