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