[Haskell-cafe] FFI and callbacks
sebastian.sylvan at gmail.com
Mon Aug 22 09:45:30 EDT 2005
On 7/23/05, Duncan Coutts <duncan.coutts at worcester.oxford.ac.uk> wrote:
> On Wed, 2005-07-20 at 16:10 +0100, Simon Marlow wrote:
> > On 20 July 2005 14:35, John Goerzen wrote:
> > > I'm looking at packaging an event-driven console widget set (CDK) for
> > > Haskell using FFI. I know that other event-driven widget sets have
> > > Haskell bindings, but I'm not quite sure how to make everything play
> > > nice with forkIO.
> > >
> > > These systems generally have some sort of an opaque main loop,
> > > implemented in C. This loop would usually never return, or perhaps
> > > only return once the UI is destroyed.
> > Is the library thread-safe or not? I mean OS-thread safe. If it is,
> > then you're home and dry: just compile your program with GHC's -threaded
> > option, and any foreign calls that need to run concurrently with Haskell
> > threads must be declared "safe" (which is the default in fact, so
> > instead I should really advise you to mark all calls that don't need to
> > run concurrently as "unsafe", because that's good for performance).
> > If the library isn't thread-safe, then you're in the same boat as Gtk
> > and wxHaskell (I believe) where there are known problems with having a
> > multithreaded Haskell GUI app.
> > You can only have one OS thread (and hence only one Haskell thread)
> > doing GUI operations, and that is the thread in the main loop.
> To be more precise, they can only be acessed from one OS thread. You can
> use multiple Haskell threads so long as they only make GUI calls from
> within the main OS thread.
> The problem then as John noted is that the main loop of these toolkits
> block and so the other Haskell threads would not get a chance to
> schedule. So the challenge is to give the Haskell threads a chance to
> Most toolkits with a main loop system allow you to setup timers. In the
> Gtk2Hs bindings we can use this trick:
> -- 50ms timeout, so GHC will get a chance to scheule about 20 times a second
> -- which gives reasonable latency without the polling generating too much
> -- cpu load.
> timeoutAddFull (yield >> return True) priorityDefaultIdle 50
> This causes the Gtk main loop to yeild to the ghc rts and give it a
> chance to run any runnable threads for a while. It is unfortunately a
> polling solution which has it's obvious disadvantages. However in
> practice it seems to generate negligable load when idle. The GHC rts
> yield function seems to be quite good about not doing much work when
> there is no work to be done!
Does anyone know how wxHaskell deals with this?
I mean is it safe to call wxHaskell GUI stuff from several threads at once?
Initial experimentation seems to suggest it is.
I wrote a simple chat client / server, and to abstract away the
networking I implemented a function "talk" which just takes a handle
and then maps input and output to that handle using two Chans.
So I basically have two threads, one which waits for stuff to be sent
out (readChan, blocking when there's nothing in it) and the other
which waits for stuff coming in (hWaitForInput h (-1), and then
writeChan to the "in" Chan).
In addition to that I, in the client GUI, spawn of a thread which just
reads the "in" channel over and over and appends whatever's coming in
to the chat area.
So that's three threads right there, plus the main thread. So to
experiment I implemented this in wxHaskell using a timer to unblock
the main loop every now and then. To make sure the performance was
visible I set it at 1000 ms. Naturally it took several seconds for all
the different threads to get a chance to do anything so sending
messages was very slow. Then I simply recompiled with "-threaded" and
everything is super fast (the timer hack isn't even necessary).
I haven't found any issues with wxHaskell misbehaving when it's called
from different threads, but I'd like to know for sure that it's
actually honest-to-goodness thread safe. So does anyone know?
More information about the Haskell-Cafe