[nhc-users] FFI "wrapper"

Donn Cave donn at avvanta.com
Wed Oct 15 02:50:16 EDT 2008


Quoth Malcolm Wallace <Malcolm.Wallace at cs.york.ac.uk>:
...
|> While I'm at it - if I manage to get callbacks working - they'll be
|> coming from various different OS-level threads, so ... I will need to
|> protect against concurrent execution, right?
|
| nhc98's runtime system is single-threaded, but assuming that the
| functions you export are pure, I don't see how that is a problem.  I
| suppose you would need somehow to route all callbacks into the OS thread
| that contained the (single) nhc98 runtime system?

Well, I suppose that's a possibility, though it would further limit
what I could do within Haskell of course.

I'm working (or playing would be more accurate) with the Haiku operating
system, essentially same API as BeOS from the '90s.  Not yet even to the
alpha release, so I'm not offended if you find the platform obscure.
Its user interface uses threads, one per window, and sends messages to
the window message port for user input etc.  The API is C++.

Just to see what would happen, I put together the trivial beginning of
a hybrid C++/Haskell application, with roughly a 5 layer structure -

  1 Haskell: trivial main, for runtime
  2 C++: application main thread, and 1 window thread
  3 Haskell: from window callback, and Haskell in independent thread
  4 C: utility wrappers
  5 C++: utility functions

The window call back runs in the window thread, of course.  The other
Haskell thread handles "the configuration" - send it a message asking
about some configuration attribute, it replies with value of that
attribute.  The configuration data accumulates in this thread's
receive/send loop, avoiding the need for module-global, mutable
configuration state that I don't know how to implement.  If I wouldn't
do that in a real application, I would sure do the same kind of thing
with a service socket connection, for example - i.e., use a separate
thread to avoid stalling the whole application waiting for network
input, and use messages to communicate with it from other threads.

It worked fine until I added that Haskell thread.  The only problem
then is that on normal termination of the application, the top level
Haskell "main = cmain" will actually go on after "cmain" returns,
jumping to where the configuration thread was, waiting for input from
the message port, when it died.  I can fix that by calling exit() from
cmain(), rather than returning, so at this point it's just a curious
behavior.

But I'm probably asking for trouble, working the runtime concurrently
from different threads, and the only reason it seems to work as well
as it does is because there isn't any actual concurrent computation
in this example program.  So what I expected I would have to do, was
something similar to what Python and I believe ocaml do, a thread
interlock that serializes access from different threads to the runtime,
The thread that holds the lock runs until an I/O operation, then
releases the lock, and tries to get it back after the I/O completes.
Now that I think about it, I guess that would mean among other things
that I couldn't use much native Haskell I/O, but I'm not far away from
that anyway.  I'm thinking it doesn't matter if different threads are
involved with the runtime, as long as it isn't concurrently.

	Donn Cave, donn at avvanta.com


More information about the Nhc-users mailing list