haskell / haskell/core-libraries-committee

Deprecate `asyncDoProc` and `asyncDoProc#` in base

Open
#366 12 comments 0 reactions 0 assignees View on GitHub
awaits-MR
Dominant language
Haskell
Stars
109
Forks
20
PR merge metrics
No merged PRs in 30d

Description

The proposal is to:
* deprecate the primop `asyncDoProc#` and the corresponding wrapper `asyncDoProc` in base
* deprecate the corresponding `BlockedOnDoProc` special thread blocking status
* eventually remove them
* no replacement or compat shim
* deprecation message to point users to Haskell FFI and `foreign import dynamic`

The motivation is that as part of the ongoing (slow) modernisation of the GHC I/O managers, we will eventually want to remove the `win32-legacy` I/O manager, and doing so will necessitate doing something about `asyncDoProc`.

So what is this thing?
```
asyncDoProc :: FunPtr (Ptr a -> IO Int) -> Ptr a -> IO Int
```
(I can't point to haddocks since it is a Win32 only export)

It asynchronously executes the given C function with an argument. It is asynchronous with respect to other Haskell threads on the capability. It is synchronous with respect to the executing thread.

The history is that this thing has been there forever. It long predates the Haskell FFI and the threaded RTS with it's support for "safe" FFI calls. It made some sense at the time.

It is however unique to the `win32-legacy` I/O manager. This means it is Windows only, and only works on the single threaded RTS. It is not supported by the new `WinIO` I/O manager, nor has it ever been supported by the `mio` I/O manager used in the threaded RTS on Windows.

It is now redundant. The same effect can be achieved in a portable way using the Haskell FFI: using "safe" FFI calls using `foreign import ccall "dynamic"`, at least on the threaded RTS. This allows invoking C function pointers (with arbitrary arguments) and of course "safe" FFI calls also do not block other Haskell threads (on the threaded RTS).

Unsurprisingly, it is used very little. A hackage search https://hackage-search.serokell.io/?q=asyncDoProc reveals only one non-trivial use. That is in cabal-install-bundle-1.18.0.2.1 where it is used to do `accept` asynchronously on Windows without using the threaded RTS.
There are also some trivial uses of the thread blocking state, mostly for rendering each state into English.

There is no great rush to remove. We could deprecate now/soon and wait a cycle or two before removing. There is not a pressing need to remove the `win32-legacy` I/O manager, since it remains the default for the non-threaded RTS. It will eventually be replaced as the default by either `WinIO` or some other new Windows I/O manager. Eventually removing `win32-legacy` will allow cleaning up a bunch of special things it does differently to all other I/O managers (like its custom thread blocking states), and unfortunate special hooks into other parts of the RTS.

Contributor guide

No contributing guide indexed for this repository

Research direction

No source file or test is named. Start by locating the base exports and RTS handling for asyncDoProc, asyncDoProc#, and BlockedOnDoProc, then review the Haskell FFI alternative using foreign import ccall "dynamic". Done means the listed APIs and blocking status are deprecated with guidance toward Haskell FFI, without adding a compatibility shim.

Written by the indexing model from the issue text.

Assessment

Tech stack
haskell
Domain
operating-systems
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.