[Haskell-cafe] MonadPrompt + Gtk2Hs = ?

Duncan Coutts duncan.coutts at worc.ox.ac.uk
Sun Jan 13 13:01:41 EST 2008

On Sun, 2008-01-13 at 14:53 -0200, Felipe Lessa wrote:

> Problem solved? Not really:
> - This kind of implementation hides lots of subtle bugs. For example,
>   because of postGUIAsync being used in Print case, the user will see
>   multiple dialog boxes at once and -- strangely enough -- he'll see
>   first the last message printed. It isn't always easy to see
>   this kind of bug at first sight, and it can be very hard to track it down.

You could use another thread :-)

That is have an output thread that reads a queue from your game engine
and only looks for the next output message at appropriate points.

> - Another problem may happen with scheduling. For some reason, there are
>   times in which it takes some time for the control to pass from the Gtk
>   thread to the forkIO one, effectively 'freezing' the game for some time.
>   Unfortunately this problem doesn't show up above, but I have experienced
>   it on a larger game I'm currently programming using Prompt.

Are you linking using -threaded or not? If not then you need another
trick to use cooperative scheduling between Gtk and the RTS.

> - It is possible that the user clicks on the button between f1 and f2.
>   Again, on this very simple example nothing seems to go wrong, but there
>   shouldn't be anything between f1 and f2 as the GUI is on an inconsistent
>   state.
> It should be noted that the scheduling problem can be mitigated using 'yield'
> on some key spots. This not only feels hackish, but also doesn't scale very
> well.

You must not be using -threaded then I'm guessing. That'd solve the

> Another approach that is sometimes adopted to solve this kind of problem is
> creating a main "sub-loop" with 'mainIteration'. This essentially removes the
> need for those nasty evil threads =).

That's pretty ugly. I'd avoid that if I were you.

Here's my suggestion: use two threads. One thread for the game logic and
one thread for communicating with the user interface. Then use an input
an output channel to post interesting events between the two. The GUI
would then also post interesting events into the incoming channel for
the view/ui thread.

Of course you'd have to link using -threaded and use postGUISync/Async
as appropriate from the view/ui thread.

By serialising all button events into a channel it allows you to ignore
button presses that happen at certain moments. And as I suggested above,
it allows you to serialise the output events so you don't end up showing
several dialogues to the user at once.


More information about the Haskell-Cafe mailing list