packages feed

shelly-extra (empty) → 0.2

raw patch · 5 files changed

+174/−0 lines, 5 filesdep +SafeSemaphoredep +basedep +shellysetup-changed

Dependencies added: SafeSemaphore, base, shelly, text

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2010, Petr Rockai <me@mornfall.net>++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Petr Rockai nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ Shelly/Background.hs view
@@ -0,0 +1,57 @@+{-# LANGUAGE OverloadedStrings #-}+module Shelly.Background (+   -- * Running external commands asynchronously.+   jobs, background, getBgResult, BgResult+) where++import Shelly+import Control.Concurrent+import qualified Control.Concurrent.MSem as Sem++-- | Create a 'BgJobManager' that has a 'limit' on the max number of background tasks.+-- an invocation of jobs is independent of any others, and not tied to the ShIO monad in any way.+-- This blocks the execution of the program until all 'background' jobs are finished.+jobs :: Int -> (BgJobManager -> ShIO a) -> ShIO a+jobs limit action = do+    unless (limit > 0) $ terror "expected limit to be > 0"+    availableJobsSem <- liftIO $ Sem.new limit+    res <- action $ BgJobManager availableJobsSem+    liftIO $ waitForJobs availableJobsSem+    return res+  where+    waitForJobs sem = do+      avail <- Sem.peekAvail sem+      if avail == limit then return () else waitForJobs sem++-- | The manager tracks the number of jobs. Register your 'background' jobs with it.+newtype BgJobManager = BgJobManager (Sem.MSem Int)++-- | Type returned by tasks run asynchronously in the background.+newtype BgResult a = BgResult (MVar a)++-- | Returns the promised result from a backgrounded task.  Blocks until+-- the task completes.+getBgResult :: BgResult a -> ShIO a+getBgResult (BgResult mvar) = liftIO $ takeMVar mvar++-- | Run the `ShIO` task asynchronously in the background, returns+-- the `BgResult a`, a promise immediately. Run "getBgResult" to wait for the result.+-- The background task will inherit the current ShIO context+-- The 'BjJobManager' ensures the max jobs limit must be sufficient for the parent and all children.+background :: BgJobManager -> ShIO a -> ShIO (BgResult a)+background (BgJobManager manager) proc = do+  state <- get+  liftIO $ do+    -- take up a spot+    -- It is important to do this before forkIO:+    -- It ensures that that jobs will block and the program won't exit before our jobs are done+    -- On the other hand, a user might not expect 'jobs' to block+    Sem.wait manager+    mvar <- newEmptyMVar -- future result++    _<- forkIO $ do+      result <- shelly $ (put state >> proc)+      Sem.signal manager -- open a spot back up+      liftIO $ putMVar mvar result+    return $ BgResult mvar+
+ shelly-extra.cabal view
@@ -0,0 +1,44 @@+Name:       shelly-extra++Version:     0.2+Synopsis:    shelly features that require extra dependencies++Description: Please see the shelly package. Shelly provides a single module for convenient+             systems programming in Haskell, similar in spirit to POSIX shells.+             .+             shelly-extra is designed to be a grab bag for functionality that+               * requires extra dependencies+             .+               * or is application specific and not generally applicable+             .+             currently contains a background job implementation for performing tasks in parallel+++Homepage:            https://github.com/yesodweb/Shelly.hs+License:             BSD3+License-file:        LICENSE+Author:              Greg Weber+Maintainer:          Greg Weber <greg@gregweber.info>+Category:            Development+Build-type:          Simple+Cabal-version:       >=1.8+++Library+  Exposed-modules:     Shelly.Background++  Build-depends: base >= 4 && < 5, shelly >= 0.10, SafeSemaphore++  ghc-options: -Wall++test-suite test+    type:           exitcode-stdio-1.0+    main-is:        main.hs+    hs-source-dirs: ., test+    ghc-options: -Wall++    Build-depends: base, text, shelly, SafeSemaphore++source-repository head+  type:     git+  location: https://github.com/yesodweb/Shelly.hs
+ test/main.hs view
@@ -0,0 +1,41 @@+{-# Language OverloadedStrings #-}+{-# Language ExtendedDefaultRules #-}+{-# Language ScopedTypeVariables #-}+{-# OPTIONS_GHC -fno-warn-type-defaults #-}++import Shelly+import Shelly.Background+import Data.Text.Lazy (Text)+default (Text)++-- smoke tests+main :: IO ()+main =+  shelly $+    -- verbosely $+    do+    jobs 2 $ \job -> do+      _<- background job $ cmd "sleep" "2"+      echo "immediate"+      _<- background job $ cmd "sleep" "2"+      echo "immediate2"+      _<- background job $ cmd "sleep" "2"+      echo "blocked by background "+ +    echo "blocked by jobs"++    setStdin "in"+    setStdin "override stdin"+    run_ "cat" ["-"]++    recho <- cmd "echo" "cmd"+    _<-cmd "echo" "bar" "baz"+    echo recho++    (res :: Text) <- cmd "pwd"+    liftIO $ putStrLn $ show res+    inspect res++    inspect =<< (cmd "echo" "compose" :: ShIO Text)+    inspect =<< (cmd "pwd")+