
On 26 Nov 2002, Alastair Reid wrote:
Umm, Alastair, I think you've got things a bit mixed up here. Did you mean two ways to create a native thread?
No.
There are currently three ways to create a Haskell thread (forkIO, foreign export, finalizers) and Wolfgang has proposed a fourth (forkNativeThread).
Invocation of a signal handler also creates a Haskell thread, doesn't it?
I was (implicitly) viewing forkIO and forkNativeThread as two variants of the same operation. Both fork a Haskell thread, one of them also creates a native thread. (It may also choose to use the native thread as the Haskell thread but that's not externally observable.)
I was putting off finalizers until the end.
1) forkNativeThread :: IO () -> IO ()
The fresh Haskell thread is associated with a fresh native thread.
(ToDo: do we really need to use a fresh native thread or would a pool of threads be ok? The issue could be avoided by separating creation of the native thread from the 'associate' operation.)
2) Calls to a threadsafe foreign export allocate a fresh Haskell thread which is then associated with the Haskell thread.
I don't know what you mean by a "threadsafe foreign export". Did you mean "threadsafe foreign import" perhaps? And I'm not sure how a fresh Haskell thread is associated with a Haskell thread ;-)
Using the bound/free terminology suggested by Seth, what I meant was "bound foreign import".
Actually, I proposed the terms, and Seth criticized the proposal. Perhaps "bound" and "unbound" might be a bit better and partially avoid the possible confusion with lambda calculus variables.
[ToDo: can Haskell threads with no associated thread make foreign calls using a thread associated with some other thread?
er... overloading the word "thread" was maybe not such a good idea. I think you're asking whether a green thread can grab a native thread to make a foreign call. The current answer is no... but can you think of a reason we might want this feature?
My question was of the form: 'is a correct implementation allowed to use a native thread even if the programmer didn't ask for it?' not 'can we make this happen?'
Sorry for all the confusion, here's the key part of the proposal again - hopefully without the ambiguity.
Haskell threads may be bound with either zero or one native threads. Binding occurs at thread creation time. There are four ways to create Haskell threads so there are four cases to consider:
How about: A Haskell thread may be bound to a native thread. Such binding occurs when the Haskell thread is created and persists for the lifetime of the Haskell thread. A Haskell thread that is not bound to a native thread is called "unbound". There are four ways ...
1) forkNativeThread :: IO () -> IO () The fresh Haskell thread is bound to a fresh native thread.
2) forkIO :: IO () -> IO () The fresh Haskell thread is not bound to a native thread.
3) Calls to a bound foreign export allocate a fresh Haskell thread which is then bound to the calling thread thread.
"... which is bound to the calling native thread" ?
Bound foreign exports have the form
foreign export bound foo :: <type>
and otherwise behave like normal foreign exports.
4) ToDo: For completeness, there ought to be a way to 'bind' finalizers to native threads but no concrete proposal currently exists.
[ToDo: The following could be simplified by saying that all foreign calls are performed by the bound thread if one exists and eliminate the concept of 'bound foreign imports'. The only reason to allow any flexibility is to allow for faster implementations.] Calls to bound foreign imports by threads which are bound to a native thread are performed by that native thread.
Bound foreign imports have the form
foreign import bound foo :: <type>
and otherwise behave like normal foreign imports.
Calls to any free (i.e., not bound) foreign imports may be made in the bound thread (if it exists) or by some other native thread at the implementation's discretion.
-- Alastair