Copyright | 2013 Joey Hess <id@joeyh.name> |
---|---|
License | BSD-2-clause |
Safe Haskell | None |
Language | Haskell98 |
Concurrent output handling.
import Control.Concurrent.Async import Control.Concurrent.Output main = withConcurrentOutput $ outputConcurrent "washed the car\n" `concurrently` outputConcurrent "walked the dog\n" `concurrently` createProcessConcurrent (proc "ls" [])
- withConcurrentOutput :: IO a -> IO a
- flushConcurrentOutput :: IO ()
- outputConcurrent :: String -> IO ()
- createProcessConcurrent :: CreateProcess -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
- waitForProcessConcurrent :: ProcessHandle -> IO ExitCode
- lockOutput :: (MonadIO m, MonadMask m) => m a -> m a
Documentation
withConcurrentOutput :: IO a -> IO a Source
Use this around any IO actions that use outputConcurrent
or createProcessConcurrent
This is necessary to ensure that buffered concurrent output actually gets displayed before the program exits.
flushConcurrentOutput :: IO () Source
Blocks until any processes started by createProcessConcurrent
have
finished, and any buffered output is displayed.
outputConcurrent :: String -> IO () Source
Displays a string to stdout, and flush output so it's displayed.
Uses locking to ensure that the whole string is output atomically even when other threads are concurrently generating output.
When something else is writing to the console at the same time, this does not block. It buffers the string, so it will be displayed once the other writer is done.
createProcessConcurrent :: CreateProcess -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) Source
Wrapper around createProcess
that prevents
multiple processes that are running concurrently from writing
to stdout/stderr at the same time.
If the process does not output to stdout or stderr, it's run by createProcess entirely as usual. Only processes that can generate output are handled specially:
A process is allowed to write to stdout and stderr in the usual way, assuming it can successfully take the output lock.
When the output lock is held (by another concurrent process,
or because outputConcurrent
is being called at the same time),
the process is instead run with its stdout and stderr
redirected to a buffer. The buffered output will be displayed as soon
as the output lock becomes free.
waitForProcessConcurrent :: ProcessHandle -> IO ExitCode Source
This must be used to wait for processes started with
createProcessConcurrent
.
This is necessary because waitForProcess
has a
race condition when two threads check the same process. If the race
is triggered, one thread will successfully wait, but the other
throws a DoesNotExist exception.
lockOutput :: (MonadIO m, MonadMask m) => m a -> m a Source
Holds a lock while performing an action that will display output.
While this is running, other threads that try to lockOutput will block,
and calls to outputConcurrent
and createProcessConcurrent
will result in that concurrent output being buffered and not
displayed until the action is done.