Search code examples
c++boostboost-asioasio

How thread-safe is boost::asio?


I have an io_context that is run by multiple threads. I'm using sockets and timers. I know that I need to wrap all async_writes by a strand to prevent concurrent writes to the socket.

But can two threads concurrently access the socket to issue an async_read and an async_write at the same time?

Or what about shutdown() or close() being called while another thread calls async_read? Or cancel() on a timer?

Do I need to protect the socket/timer with a mutex or strand in this cases?


Solution

  • This has oft been asked and answered:

    Thread Safety

    In general, it is safe to make concurrent use of distinct objects, but unsafe to make concurrent use of a single object. However, types such as io_context provide a stronger guarantee that it is safe to use a single object concurrently.

    So yes, you need to protect active accesses to you timer/socket objects. However, having asynchronous operations in flight is not a concern: it's about your accesses that require your synchronization.

    So,

     asio::post(strand, [&sock] { sock.shutdown();});
    

    is always safe, and when you have only 1 thread running the service, then

    post(io_context_, [&sock] { sock.shutdown();});
    

    is also fine. Both will have the effect of safely canceling any asynchronous operations still in flight on sock.

    See also the excellent: Why do I need strand per connection when using boost::asio?