Re: Keeping program flow moving nicely



"Timothy M. Shead" wrote:
> 
> 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

If you want the user to "see" the moves then 500 ms may be better,
perhaps even allow the user to set the "move_delay".

-- 
We stand on the shoulders of those giants who coded before.
Build a good layer, stand strong, and prepare for the next wave.
Guide those who come after you, give them your shoulder, lend them your code.
Code well and live!   - gmd slip net (7th Coding Battalion)




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