packages feed

streaming-commons 0.1.3.1 → 0.1.4

raw patch · 3 files changed

+178/−1 lines, 3 filesdep +processdep +stm

Dependencies added: process, stm

Files

+ Data/Streaming/Process.hs view
@@ -0,0 +1,137 @@+-- | A full tutorial for this module is available on FP School of Haskell:+-- <https://www.fpcomplete.com/user/snoyberg/library-documentation/data-streaming-process>.+--+-- Note that, while the tutorial covers @Data.Streaming.Process@, this module is+-- the basis of the streaming version, and almost all concepts there apply here.+module Data.Streaming.Process+    ( -- * Functions+      streamingProcess+      -- * Specialized streaming types+    , Inherited (..)+    , ClosedStream (..)+    , UseProvidedHandle (..)+      -- * Process handle+    , StreamingProcessHandle+    , waitForStreamingProcess+    , waitForStreamingProcessSTM+    , getStreamingProcessExitCode+    , getStreamingProcessExitCodeSTM+    , streamingProcessHandleRaw+    , streamingProcessHandleTMVar+      -- * Type classes+    , InputSource+    , OutputSink+      -- * Reexport+    , module System.Process+    ) where++import           Control.Applicative             ((<$>), (<*>))+import           Control.Concurrent              (forkIO)+import           Control.Concurrent.STM          (STM, TMVar, atomically,+                                                  newEmptyTMVar, putTMVar,+                                                  readTMVar, tryReadTMVar)+import           Control.Monad.IO.Class          (MonadIO, liftIO)+import           Data.Maybe                      (fromMaybe)+import           Data.Streaming.Process.Internal+import           System.Exit                     (ExitCode)+import           System.IO                       (hClose)+import           System.Process++-- | Use the @Handle@ provided by the @CreateProcess@ value. This would allow+-- you, for example, to open up a @Handle@ to a file, set it as @std_out@, and+-- avoid any additional overhead of dealing with providing that data to your+-- process.+--+-- Since 0.1.4+data UseProvidedHandle = UseProvidedHandle++-- | Inherit the stream from the current process.+--+-- Since 0.1.4+data Inherited = Inherited++-- | Close the stream with the child process.+--+-- Since 0.1.4+data ClosedStream = ClosedStream++instance InputSource ClosedStream where+    isStdStream = (\(Just h) -> hClose h >> return ClosedStream, Just CreatePipe)+instance InputSource Inherited where+    isStdStream = (\Nothing -> return Inherited, Just Inherit)+instance InputSource UseProvidedHandle where+    isStdStream = (\Nothing -> return UseProvidedHandle, Nothing)++instance OutputSink ClosedStream where+    osStdStream = (\(Just h) -> hClose h >> return ClosedStream, Just CreatePipe)+instance OutputSink Inherited where+    osStdStream = (\Nothing -> return Inherited, Just Inherit)+instance OutputSink UseProvidedHandle where+    osStdStream = (\Nothing -> return UseProvidedHandle, Nothing)++-- | Blocking call to wait for a process to exit.+--+-- Since 0.1.4+waitForStreamingProcess :: MonadIO m => StreamingProcessHandle -> m ExitCode+waitForStreamingProcess = liftIO . atomically . waitForStreamingProcessSTM++-- | STM version of @waitForStreamingProcess@.+--+-- Since 0.1.4+waitForStreamingProcessSTM :: StreamingProcessHandle -> STM ExitCode+waitForStreamingProcessSTM = readTMVar . streamingProcessHandleTMVar++-- | Non-blocking call to check for a process exit code.+--+-- Since 0.1.4+getStreamingProcessExitCode :: MonadIO m => StreamingProcessHandle -> m (Maybe ExitCode)+getStreamingProcessExitCode = liftIO . atomically .  getStreamingProcessExitCodeSTM++-- | STM version of @getStreamingProcessExitCode@.+--+-- Since 0.1.4+getStreamingProcessExitCodeSTM :: StreamingProcessHandle -> STM (Maybe ExitCode)+getStreamingProcessExitCodeSTM = tryReadTMVar . streamingProcessHandleTMVar++-- | Get the raw @ProcessHandle@ from a @StreamingProcessHandle@. Note that+-- you should avoid using this to get the process exit code, and instead+-- use the provided functions.+--+-- Since 0.1.4+streamingProcessHandleRaw :: StreamingProcessHandle -> ProcessHandle+streamingProcessHandleRaw (StreamingProcessHandle ph _) = ph++-- | Get the @TMVar@ storing the process exit code. In general, one of the+-- above functions should be used instead to avoid accidentally corrupting the variable\'s state..+--+-- Since 0.1.4+streamingProcessHandleTMVar :: StreamingProcessHandle -> TMVar ExitCode+streamingProcessHandleTMVar (StreamingProcessHandle _ var) = var++-- | The primary function for running a process. Note that, with the+-- exception of 'UseProvidedHandle', the values for @std_in@, @std_out@+-- and @std_err@ will be ignored by this function.+--+-- Since 0.1.4+streamingProcess :: (MonadIO m, InputSource stdin, OutputSink stdout, OutputSink stderr)+               => CreateProcess+               -> m (stdin, stdout, stderr, StreamingProcessHandle)+streamingProcess cp = liftIO $ do+    let (getStdin, stdinStream) = isStdStream+        (getStdout, stdoutStream) = osStdStream+        (getStderr, stderrStream) = osStdStream++    (stdinH, stdoutH, stderrH, ph) <- createProcess cp+        { std_in = fromMaybe (std_in cp) stdinStream+        , std_out = fromMaybe (std_out cp) stdoutStream+        , std_err = fromMaybe (std_err cp) stderrStream+        }++    ec <- atomically newEmptyTMVar+    _ <- forkIO $ waitForProcess ph >>= atomically . putTMVar ec++    (,,,)+        <$> getStdin stdinH+        <*> getStdout stdoutH+        <*> getStderr stderrH+        <*> return (StreamingProcessHandle ph ec)
+ Data/Streaming/Process/Internal.hs view
@@ -0,0 +1,36 @@+module Data.Streaming.Process.Internal+    ( StreamingProcessHandle (..)+    , InputSource (..)+    , OutputSink (..)+    ) where++import           Control.Concurrent.STM (TMVar)+import           System.Exit            (ExitCode)+import           System.IO              (Handle)+import           System.Process         (ProcessHandle, StdStream (CreatePipe))++-- | Class for all things which can be used to provide standard input.+--+-- Since 0.1.4+class InputSource a where+    isStdStream :: (Maybe Handle -> IO a, Maybe StdStream)+instance InputSource Handle where+    isStdStream = (\(Just h) -> return h, Just CreatePipe)++-- | Class for all things which can be used to consume standard output or+-- error.+--+-- Since 0.1.4+class OutputSink a where+    osStdStream :: (Maybe Handle -> IO a, Maybe StdStream)+instance OutputSink Handle where+    osStdStream = (\(Just h) -> return h, Just CreatePipe)++-- | Wraps up the standard @ProcessHandle@ to avoid the @waitForProcess@+-- deadlock. See the linked documentation from the module header for more+-- information.+--+-- Since 0.1.4+data StreamingProcessHandle = StreamingProcessHandle+    ProcessHandle+    (TMVar ExitCode)
streaming-commons.cabal view
@@ -1,5 +1,5 @@ name:                streaming-commons-version:             0.1.3.1+version:             0.1.4 synopsis:            Common lower-level functions needed by various streaming data libraries description:         Provides low-dependency functionality commonly needed by various streaming data libraries, such as conduit and pipes. homepage:            https://github.com/fpco/streaming-commons@@ -24,6 +24,8 @@                        Data.Streaming.Filesystem                        Data.Streaming.Network                        Data.Streaming.Network.Internal+                       Data.Streaming.Process+                       Data.Streaming.Process.Internal                        Data.Streaming.Text                        Data.Streaming.Zlib                        Data.Streaming.Zlib.Lowlevel@@ -43,6 +45,8 @@                      , directory                      , network                      , random+                     , process+                     , stm                      , text                      , transformers                      , zlib