In the FFI, there are two ways to annotate a foreign call:
- safe (the default). This means the foreign call can invoke a foreign export, and hence re-enter Haskell.
- unsafe. The programmer guarantees that the foreign call cannot re-enter Haskell, and the implementation may use this information to optimize the call.
Additionally in GHC, "safe" means that the call should not prevent other Haskell threads from making progress. It indicates a concurrent foreign call (see Concurrency).
If the standard is to include concurrency, then it is a significant burden to include the full functionality of "safe" foreign calls as implemented by GHC as a requirement. It would imply that the runtime must be able to handle multi-threaded call-in, that is, call-ins from multiple OS threads simultaneously. In contrast, if the implementation only has to handle call-ins that occur during a synchrounous call-out, the implementation is much simpler.
There are simpler positions that can be adopted that reduce the requirements on the implementation. The current proposal is this:
- concurrent indicates a foreign call that runs concurrently with other running Haskell threads.
- nonreentrant (pure has also been suggested) indicates that the foreign call does not invoke and Haskell code.
and the standard would only require that concurrent is supported with nonreentrant; concurrent alone is an extension. The standard would also clarify that multi-threaded call-in is not a requirement.