[Haskell-cafe] FFI and callbacks

Simon Marlow simonmar at microsoft.com
Wed Jul 20 11:45:33 EDT 2005


On 20 July 2005 16:23, John Goerzen wrote:

> On Wed, Jul 20, 2005 at 04:10:38PM +0100, Simon Marlow wrote:
>> On 20 July 2005 14:35, John Goerzen wrote:
>>> 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). 
> 
> That's half of the question.  The other half is: what is the canonical
> way of handling this mainloop that doesn't return from Haskell?  Do we
> just treat it that way in Haskell as well, or would some people forkIO
> it?

You could forkIO the main loop if you want; it shouldn't make any
difference, except that GHC terminates the program when the main thread
completes, so it's more convenient to have the main loop run in the main
thread, so that the program terminates when the main loop returns.

> Does any part of your answer vary depending on whether the Haskell
> threads in question are forkIO threads or forkOS threads?  I imagine
> that it might.

No, and I don't think you need forkOS here.

This paper might help shed some light:

 http://www.haskell.org/~simonmar/papers/conc-ffi.pdf

>> 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 
> 
> What about multiple forkIO threads?

You should think of Haskell as having a one-to-one mapping between OS
threads and Haskell threads.  The only difference between forkIO and
forkOS is that a forkIO thread can migrate from one OS thread to
another, whereas a forkOS thread always runs on the same OS thread.
This difference is therefore only visible when you make FFI calls,
because there's no way in Haskell to tell what OS thread you're running
on.

In practice, GHC uses an optimised implementation to take advantage of
the fact that forkIO threads are allowed to migrate from one OS thread
to another, and it runs all the forkIO threads using a small pool of
worker OS threads.

The design of forkIO/forkOS and the FFI is carefully crafted to
accommodate both GHC's optimised implementation and simpler
implementations such as one-to-one or a giant lock.

>> thread in the main loop.  You have to somehow set up a communication
>> between your other Haskell threads and the thread running the main
>> loop - perhaps you can send requests of type (IO ()) down a channel
>> to the main loop thread which wakes up occasionally to run them, for
>> example. 
> 
> I imagine there could be exceptions to this..  For instance, perhaps a
> given operation needs to do 5 things, perhaps simultaneously, before
> displaying a result.  It could, perhaps, fire off five threads and
> just not display a result until all five have terminated, yes?

Sure, but it's just a matter of converting direct GUI calls into RPCs to
the GUI thread, using some appropriate RPC mechanism.

Cheers,
	Simon


More information about the Haskell-Cafe mailing list