|
Boost Users : |
Subject: [Boost-users] [asio] Pending handlers not invoked in boost.asio?
From: Germán Diago (germandiago_at_[hidden])
Date: 2011-05-08 05:20:55
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.
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net