Boost logo

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