Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

concurrently doesn't compose well with forever #113

Open
infinity0 opened this issue May 29, 2020 · 0 comments
Open

concurrently doesn't compose well with forever #113

infinity0 opened this issue May 29, 2020 · 0 comments

Comments

@infinity0
Copy link

Suppose I want to compose a bunch of reads in the way select(2) does, then it's very tempting to write something like forever $ race (forever $ read a) (forever $ read b).

However looking at the implementation this won't work correctly, since new threads are created and killed on every call to race. So when one action "wins", the other actions are killed, but they might have consumed their streams in the meantime.

It's possible to create an implementation that does work properly, although it has to compose with forever inside the action - something like:

foreverInterleave :: [IO r] -> IO (IO r, IO (), IO())

where running (_1, _2, _3) <- foreverConcurrently reads would itself give further actions to be run, that behave as follows:

  1. an action that gets any of the results, whichever arrives first, in order
  2. an action that waits for any ongoing actions to finish, as well as all their results to be consumed ("graceful shutdown") by the caller calling (1)
  3. an action that kills the ongoing threads, potentially dropping any unconsumed values, but can return immediately ("ungraceful shutdown")

The implementation ideally would avoid running the original actions, unless (1) has indicated a concrete demand for them.

Does that seem like something sensible for this library? I will have to write code that does this anyway in one of my projects, I can contribute it here for others too. Note that the existance of this function here might help other people avoid bugs in their code, since the incorrect-but-obvious version forever $ race (forever $ read a) (forever $ read b) at a first glance seems perfectly acceptable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant