I am studying the use of Boost ASIO. Below is the code copied from the chat example along with the Boost ASIO documentation,
typedef std::deque<chat_message> chat_message_queue; class chat_client { public: chat_client(boost::asio::io_service& io_service, tcp::resolver::iterator endpoint_iterator) : io_service_(io_service), socket_(io_service) { boost::asio::async_connect(socket_, endpoint_iterator, boost::bind(&chat_client::handle_connect, this, boost::asio::placeholders::error)); } void write(const chat_message& msg) { io_service_.post(boost::bind(&chat_client::do_write, this, msg)); } void close() { io_service_.post(boost::bind(&chat_client::do_close, this)); } private: void handle_connect(const boost::system::error_code& error) { //Implementation } void handle_read_header(const boost::system::error_code& error) { //Implementation } void handle_read_body(const boost::system::error_code& error) { //Implementation } void do_write(chat_message msg) { bool write_in_progress = !write_msgs_.empty(); write_msgs_.push_back(msg); if (!write_in_progress) { boost::asio::async_write(socket_, boost::asio::buffer(write_msgs_.front().data(), write_msgs_.front().length()), boost::bind(&chat_client::handle_write, this, boost::asio::placeholders::error)); } } void handle_write(const boost::system::error_code& error) { //Implementation } void do_close() { socket_.close(); } private: boost::asio::io_service& io_service_; tcp::socket socket_; chat_message read_msg_; chat_message_queue write_msgs_; };
The write_msgs_ is asynchronous and there are no locks around the member variables write_msgs_ and read_msgs_ . Should there be a problem with concurrency here?
Is it safe to call post calls from a thread that runs io_service::run? What about dispatch ? What to do with the same call from threads that do not work io_service::run ?
In doSend() , why do they push the message on write_msgs_ instead of sending directly? Also in the same function, why do they check if write_msgs_ empty, and only if it is not, by sending? Does write_msgs_.empty() = false record? How?
If do_write() is called in only one thread, why do I need a queue to maintain the send sequence? Wouldn't io_service finish the task and then do the asynchronous operation do_write by do_write ? Will using dispatch instead of post matter in the example mentioned above?
source share