Bound Threads

Daan Leijen daanleijen at
Fri Mar 14 05:38:29 EST 2003

Hi all,

I have just spend some time reading through all the discussions and the
new "threads" document and I would like to propose the addition of a new library function.

> forkOS :: IO () -> IO ThreadID

The function "forkOS" forks a new Haskell thread that runs in a new OS (or
native) thread. With this, I also propose that "forkIO" always runs a Haskell thread in the same OS thread that the current Haskell thread runs in.
(i.e. "forkIO": same OS thread, "forkOS": new OS thread)

Using the new primitive, we can view the new "threadsafe" keyword as
syntactic sugar:

> foreign import threadsafe foo :: Int -> IO Int


> foo :: Int -> IO Int
> foo i = threadSafe (primFoo i)
> foreign import "foo" primFoo :: IO Int


> threadSafe :: IO a -> IO a
> threadSafe io
> = do result <-newEmptyMVarforkOS (do{ x <-io; putMVar result x })
> getMVar result

Note that "forkOS" can use thread pooling in its implementation.

The advantage of a separate function "forkOS" is that we put control back
to the users hands, as a programmer can be very specific about which Haskell
threads are part of a certain OS thread and can be specific about the OS
thread that is used to run a foreign function. On other words, it is absolutely
clear to which OS thread a Haskell thread is bound. In this respect, it helps
to have another function that runs a Haskell thread in a specific OS thread.

> getOSThread :: ThreadID -> OSThreadID
> forkIOIn :: OSThreadID -> IO () -> IO ThreadID

I have the feeling that it is not difficult to implement "forkOS" and family
once the runtime system has been upgraded to support multiple OS threads.
Wolfgang, you seem to be the expert on the OS thread area, would it be hard?

I am not saying that we should discard the "threadsafe" keyword as it might
be a useful shorthand, but I think that it is in general a mistake to try to keep the management of OS threads implicit -- don't use new keywords, add combinators to implement them!

I feel that the following has happened; urk, we need some way of keeping haskell threads running while calling C; we add "threadsafe"; whoops, sometimes
a function expects that it is run in the same OS thread; we add "bound"; whoops, sometimes functions expect to be run from a specific OS thread... unsolved??
Before we know it, we have added tons of new keywords to solve the wrong problem.

Maybe it is time to take a step back and use a somewhat lower level model with
two fork variants: "forkIO" (in the same OS thread) and "forkOS" (in a new OS thread).
It seems that none of the above problems occur when having explicit control.
In general it seems that OS threads are a resource that is too subtle to be managed automatically as they have a profound impact on how libraries are used and applications are structured.

All the best,

"worse is better" :-)

More information about the FFI mailing list