Skip to content

concurrently doesn't compose well with forever #113

Open

Description

@infinity0

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions