Re: Keeping program flow moving nicely



Dave Neary wrote:

Hi all,

I'm involved in writing a gnome/gtk game which has thrown up a minor problem I hope you guys can help me with.

The game has computer players of varying strengths, and it's possible for the computer to play itself. That's fine, but the way we've been handling program flow was by checking, after processing a move, whether it was the turn of a computer to move, and based on that call the function to process a move for the computer, a la
gint process_move(gint move)
{
...
    switch_players();
    if (is_computer(currentPlayer))
    {
        process_move(get_computer_move(state));
    }
    return 0;
}

This has been seizing control of the program and blocking any events whenever it's a computer move, which is a pain when we have two computers playing each other, when control never gets restored to gtk_main() until the end of the game.

We've hacked fixes to this which aren't very pretty, although they're effective. One is to process all pending gdk events before the call to process_move() above. The second was to put the check above in a function which we attached to the idle loop, so that process_move() terminates normally and without calling itself. We didn't really think either of these were ideal. The first is just hackish, and the second means that every single idle loop we're checking whether it's the computer's turn, and this makes things much more processor intensive than they should be.

We wanted a way to allow the process_move() function to terminate normally , and still get called properly every time it was the computer's turn. Due to an incomplete understanding of signal handling, I thought this could be done by writing a composite widget which added a new signal which we could emit at the end of process_move, and attaching a callback to it that would call process_move() with the computer's move. Obviously this didn't achieve the desired goal, since the signal getting emitted wa strapped, and we end up in the same cycle as the original - the callback recursively emits the signal until either the game is over, or we seg fault :) (thankfully, the former happens).

What I want to know is how we can emit this signal, and get the computer's move processed, without interfering with other events that might happen in the meantime? Sorry if this mail is very long - I probably went into too much detail about what I'd done, and how I've arrived at where I'm at. My incorrect assumption about signals, by the way, way that emitting a signal would just add that signal to the queue of unprocessed signals/events, and have it handled in order.

Thanks a lot,
Dave.

Use gtk_timeout_add() to create a 'timeout' signal that gets called, say, every 100 milliseconds or so. In your handler for the timeout event you decide whose turn it is and call process_move(). The timeout event will get called frequently enough that there won't be any noticeable delay, between moves but you won't be dragging down the CPU (as you would if you used an idle handler). At the same time, normal events will continue to be processed without any intervention on your behalf, so the human user can hit pause, cancel, or whatever.

Regards,
Timothy M. Shead





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]