Michael Hobbs <[EMAIL PROTECTED]> wrote,

> "Manuel M. T. Chakravarty" wrote:
> > Therefore, I propose to have three kinds of FFI calls:
> > 
> >   unsafe    - as before
> >   safe      - as currently implemented
> >   supersafe - (or call it "threadsafe" or "blocksafe")
> >               the solution you described above
> > 
> > I think, the trouble of having to deal with three kinds of
> > calls is worthwhile as
> > 
> > (a) "unsafe" and "safe" can be part of a standard FFI;
> >     "supersafe" is only added by implementations that also
> >     support multi-threading;
> > (b) bindings to non-thread-safe libraries can use "unsafe"
> >     and "safe"; in a multi-threaded RTS, they are, so to
> >     speak, included into the lock that protects the Haskell
> >     heap etc; and
> > (c) if a programmer knows that a call cannot block, but may
> >     re-enter the Haskell scheduler, "safe" provides a faster
> >     way of doing the call.
> 
> I don't think that these three FFI types are enough to cover *all* of
> the bases regarding callbacks, blocking, and thread-safety. 
> 
> As a diabolical example, say that I really wanted a multithreaded GTK+
> application. Say, for example, a ray-trace program where the tracing
> engine is running on a separate thread than the GUI. The GUI updates the
> display every few seconds and can stop, start, pause the engine
> concurrently. Every GTK+ program calls gtk_main(), which won't return
> until the program ends. It's conceptually vague whether or not to
> classify gtk_main() as blocking or not, since it does invoke callbacks.
> But at any rate, I want to keep the GTK+ FFI calls within a single OS
> thread, because GTK+ is not terribly thread-safe, but I also want the
> ray-tracing engine to run concurrently on a separate Haskell thread.
> Which of the three types above would you use when defining gtk_main()?

Given the current status of thread safety in GTK+, without
further provisions, gtk_main() would be called "safe" (but
not "threadsafe").  As a consequence, you cannot have the
ray-tracer running interleaved with gtk_main().  That's a
pity, but a problem of GTK+ and not the GHC RTS.  

If we want to have this functionality with GTK+, the only
clean way, I think, is to insert appropriate mutex
operations to the GTK+ binding.  After we have done this, we 
can use "threadsafe" to call gtk_main().

My point here is that, in the RTS, "unsafe", "safe", and
"threadsafe" is enough.  The rest is a problem of the
libraries and library bindings.

> However, I'm not really sure what "thread-safe"
> function means, within the Haskell FFI. It could be that no two
> thread-safe functions can be executing at the same time. Or, it could
> mean that any callbacks that a "thread-safe" function makes are run on
> the same OS thread as that function. 

Following the reverse naming scheme of the FFI paper:

  unsafe         - the RTS makes no special provisions and just
                   calls the C function (this means the function
                   must be well-behaved: no re-entry into the
                   Haskell scheduler and no blocking if you
                   don't want to block the whole Haskell system)
  safe           - the RTS cleans things up, to allow the called
                   function to re-enter the Haskell scheduler (but
                   if the function blocks, the whole Haskell
                   evaluation still blocks)
  threadsafe     - the RTS executes the foreign call in a
  (or supersafe)   seperate OS thread (the function can do what
                   it likes)

The label does NOT describe a property of the function, but
it describes the strategy of the RTS.  For "safe" calls, the 
RTS plays safe, for "threadsafe" calls it plays supersafe.

Manuel

Reply via email to