Chris
Chris

Reputation: 35

using boost async API's with multiple threads

Regarding this post: Why do I need strand per connection when using boost::asio?

I'm focusing on this statement regarding async calls: "However, it is not safe for multiple threads to make calls concurrently"

This example: http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/example/cpp11/chat/chat_client.cpp

If I refer to main as "thread 1" and the spawned thread t as "thread 2", then it seems like thread 1 is calling async_write (assuming no write_in_progress) while thread 2 is calling async_read. What am I missing?

Upvotes: 0

Views: 1534

Answers (1)

Tanner Sansbury
Tanner Sansbury

Reputation: 51881

In the official chat example, chat_client::write() defers work to the io_service via io_service::post(), which will:

  • request that the io_service execute the given handler via a thread that is currently invoking the poll(), poll_one(), run(), or run_one() function on the io_service
  • not allow the given handler to be invoked within the calling function (e.g. chat_client::write())

As only one thread is running the io_service, and all socket read, write, and close operations are only initiated from handlers that have been posted to the io_service, the program satisfies the thread-safety requirement for socket.

class chat_client
{
  void write(const chat_message& msg)
  {
    // The nullary function `handler` is created, but not invoked within
    // the calling function.  `msg` is captured by value, allowing `handler`
    // to append a valid `msg` object to `write_msgs_`.
    auto handler = [this, msg]()
      {
        bool write_in_progress = !write_msgs_.empty();
        write_msgs_.push_back(msg);
        if (!write_in_progress)
        {
          do_write();
        }
      };

    // Request that `handler` be invoked within the `io_service`.
    io_service_.post(handler);
  }
};

Upvotes: 2

Related Questions