[asio] Pending handlers not invoked in boost.asio?

Hello. I'm writing a little game which keeps four players connected. At first, my protocol does something like the following: -Server waits for 3 incoming connections. io_service::run is running in another thread (and the code I'll show you server side is executed after that). -Clients connect and send its data (name and team). When everything's done, the server continues and shows the received data from the clients. I have a loop like this on the Server side (with the great coroutine implementation from the examples): for (; num_players_connected_ !=3; ++num_players_connected_) { //Create context connection_contexts_.at(num_players_connected_) = std::make_shared<ConnectionContext>(service_); yield acceptor_.async_accept(*connection_contexts_.at(num_players_connected_)->socket(), std::ref(*this)); std::cout << "Servidor: Incoming connection" << std::endl; connection_contexts_.at(num_players_connected_)->start(); //This calls ClientContext::operator() //Start connection processing std::cout << "Servidor: Players connected: " << num_players_connected_ << std::endl; } //Here every connection is already done but must wait for data available in every context. std::cout << "Server: All " << num_players_connected_ << " players are connected" << std::endl; for (std::size_t i = 0; i < 3; i++) { //Wait for each player to have its data available server-side connection_contexts_.at(i)->playerDataReady().get(); std::cout << "Player info:\n"; std::cout << "\tPlayer name " << connection_contexts_.at(i)->playerName() << std::endl; std::cout << "\tPlayer team " << connection_contexts_.at(i)->playerTeam() << std::endl; } /////////////////////////////////// The Context for each client in the server side looks something like this: void ClientContext::operator()() { using namespace boost; const MsjDatosJugador * player_data = 0; MensajeRed msg; reenter (coro_opcall_state_) { yield asyncReadMessageFromSocketIntoQueue(std::ref(*this)); msg = getNextMessage(); std::cout << "Message has been read\n" << std::endl; if (msg.getTipo() == typeid(MsjDatosJugador)) { player_data = &(msg.getInfo<MsjDatosJugador>()); player_name_ = std::move(player_data->name_); player_team_ = player_data->team_; player_ready_ = true; } else { message_received_handler_(getNextMessage()); } } } void ClientContext::asyncReadMessageFromSocketIntoQueue( std::function<void ()> handler, const boost::system::error_code & ec, std::size_t bytes) { using namespace boost; if (!ec) { reenter (coro_read_state_) { message_size_ = std::make_shared<boost::int64_t>(); yield asio::async_read(*socket_, asio::buffer(message_size_.get(), sizeof(boost::int64_t)), std::bind(&GuinyoteClientContext::asyncReadMessageFromSocketIntoQueue, this, handler, std::placeholders::_1, std::placeholders::_2)); message_buffer_ = std::make_shared<std::vector<char> >(*message_size_); yield asio::async_read(*socket_, asio::buffer(message_buffer_->data(), *message_size_), std::bind(&GuinyoteClientContext::asyncReadMessageFromSocketIntoQueue, this, handler, std::placeholders::_1, std::placeholders::_2)); std::istringstream stream(std::string(message_buffer_->begin(), message_buffer_->end()), std::ios::binary); boost::archive::binary_iarchive archive(stream); MensajeRed msg; archive >> msg; std::cout << "GuinyoteClientContext: Pushing message into the message queue.\n"; messages_.push(msg); handler(); } } else { BOOST_THROW_EXCEPTION(std::runtime_error("GuinyoteContext: Error reading from client socket: " + ec.message())); } } My EXACT problem is that when the THIRD client connects, after invoking ClientContext::asyncReadMessageFromSocketIntoQueue once and reaching the first yield, it is never invoked again, even if I passed the handler function. Am I missing something? Must I flush the io_service handler execution in some way? Thanks in advance.

My EXACT problem is that when the THIRD client connects, after invoking ClientContext::asyncReadMessageFromSocketIntoQueue once and reaching the first yield, it is never invoked again, even if I passed the handler function.
I don't have answers to your questions, but I just would like to bring to your attention that, IUUC, Coroutines are neigher a part of official asio release, nor a part of boost, so there're little chances that many people are familiar with this library.

Hi,
My EXACT problem is that when the THIRD client connects, after invoking ClientContext::asyncReadMessageFromSocketIntoQueue once and reaching the first yield, it is never invoked again, even if I passed the handler function.
I don't have answers to your questions, but I just would like to bring to your attention that, IUUC, Coroutines are neigher a part of official asio release, nor a part of boost, so there're little chances that many people are familiar with this library.
it's in /libs/asio/example/http/server4/coroutine.hpp and basically works with one huge switch-case construct. -- Best regards, michi7x7

it's in /libs/asio/example/http/server4/coroutine.hpp and basically works with one huge switch-case construct.
I suspect that the problem has nothing to do with coroutines, since the two former contexts worked well and every context is independent from the others (they don't share data). The third one is not invoked BECAUSE the handler (which is scheduled after the last call to Context::asyncReadFromSocketIntoQueue) is not called, even if it's been scheduled for execution. So my question, actually, has nothing to do with coroutines (that part has been checked by me and, I suspect that it's not coroutine's fault (although it could be).
participants (3)
-
Germán Diago
-
Igor R
-
michi7x7