FFI, safe vs unsafe

Marcin 'Qrczak' Kowalczyk qrczak at knm.org.pl
Wed Apr 12 18:43:26 EDT 2006


John Meacham <john at repetae.net> writes:

> I object to the idea that concurrent calls are 'safer'. getting it
> wrong either way is a bug. it should fail in the most obvious way
> rather than the way that can remain hidden for a long time.

I wouldn't consider it a bug of an implementation if it makes a call
behave like concurrent when it's specified as non-concurrent. If a
library wants to make it a critical section, it should use a mutex
(MVar).

Or there should be another kind of foreign call which requires
serialization of calls. But of which calls? it's rarely the case that
it needs to be serialized with other calls to the same function only,
and also rare that it must be serialized with everything else, so the
granularity of the mutex must be explicit. It's fine to code the mutex
explicitly if there is a kosher way to make it global.

Non-concurrent calls which really blocks other thread should be
treated only as an efficiency trick, as in implementations where the
runtime is non-reentrant and dispatches threads running Haskell code
internally, making such call without ensuring that other Haskell
threads have other OS threads to run them is faster.

OTOH in implementations which run Haskell threads truly in parallel,
the natural default is to let C code behave concurrently. Ensuring
that it is serialized would require extra work which is counter-productive.
For functions like sqrt() the programmer wants to say that there is no
need to make it concurrent, without also saying that it requires calls
to be serialized.

> Which is why I'd prefer some term involving 'blocking' because that
> is the issue. blocking calls are exactly those you need to make
> concurrent in order to ensure the progress guarentee.

What about getaddrinfo()? It doesn't synchronize with the rest of the
program, it will eventually complete no matter whether other threads
make progress, so making it concurrent is not necessary for correctness.
It should be made concurrent nevertheless because it might take a long
time. It does block; if it didn't block but needed the same time for
an internal computation which doesn't go back to Haskell, it would
still benefit from making the call concurrent.

It is true that concurrent calls often coincide with blocking. It's
simply the most common reason for a single non-calling-back function
to take a long time, and one which can often be predicted statically
(operations of extremely long integers might take a long time too,
but it would be hard to differentiate them from the most which don't).

The name 'concurrent' would be fine with me if the default is 'not
necessarily concurrent'. If concurrent calls are the default, the name
'nonconcurrent' is not so good, because it would seem to imply some
serialization which is not mandatory.

-- 
   __("<         Marcin Kowalczyk
   \__/       qrczak at knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/


More information about the Haskell-prime mailing list