On Sun, Nov 5, 2017 at 6:00 AM, Phil Sean via Boost-users
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!