0

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?

Community
  • 1
  • 1
Chris
  • 35
  • 6

1 Answers1

2

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);
  }
};
Tanner Sansbury
  • 51,153
  • 9
  • 112
  • 169
  • Interesting. That io_service::post is definitely a difference between the chat example I was looking at (v1.55) and the latest chat example (v1.61). So, it appears as if someone noticed exactly the same thing as I did and fixed it. I'll stick to the latest version from now on. – Chris Jun 14 '16 at 01:31
  • @Chris Perhaps the example was not an official example? `io_service.post` is in the [1.55 C++11 chat client](https://github.com/boostorg/asio/blob/boost-1.55.0/example/cpp11/chat/chat_client.cpp#L35) and has been used in the example since Asio was accepted to Boost (see [1.35 chat example](http://www.boost.org/doc/libs/1_35_0/doc/html/boost_asio/example/chat/chat_client.cpp)). – Tanner Sansbury Jun 14 '16 at 02:01
  • My link goes to boost.org...which is official as far as I know. It also shows up high in google search, but I can't remember exactly what I searched. Maybe you are saying that file exists on their server but is not part of the official documentation for 1.55. Could be. It doesn't have the "home" and arrow buttons in the lower right of the page like I've seen in other boost.org documentation. If you look at the page I linked...io_service::post is missing, then click the link at the top to take you to the "latest version of this page" and io_service::post shows up. Odd. – Chris Jun 14 '16 at 03:20
  • Well, now io_service::post is showing up in my link. I give up. It is voodoo I tell you. – Chris Jun 14 '16 at 03:23