packages feed

extra 1.1 → 1.2

raw patch · 8 files changed

+55/−12 lines, 8 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Data.List.Extra: instance GHC.Show.Show Data.List.Extra.Color
- Data.List.Extra: instance GHC.Show.Show a => GHC.Show.Show (Data.List.Extra.RB a)
- System.Time.Extra: instance GHC.Classes.Eq System.Time.Extra.Timeout
- System.Time.Extra: instance GHC.Exception.Exception System.Time.Extra.Timeout
- System.Time.Extra: instance GHC.Show.Show System.Time.Extra.Timeout
+ Control.Concurrent.Extra: onceFork :: IO a -> IO (IO a)
+ Data.List.Extra: instance Show Color
+ Data.List.Extra: instance Show a => Show (RB a)
+ Extra: onceFork :: IO a -> IO (IO a)
+ System.Time.Extra: instance Eq Timeout
+ System.Time.Extra: instance Exception Timeout
+ System.Time.Extra: instance Show Timeout
+ System.Time.Extra: instance Typeable Timeout

Files

CHANGES.txt view
@@ -1,5 +1,10 @@ Changelog for Extra +1.2+    Add onceFork+    Make once async exception safe+    Fix a deadlock in once when two people request in parallel+    Fix a missing hClose in captureOutput 1.1     #7, add nubOrd, nubOrdOn, nubOrdBy     #6, add groupSortOn and groupSortBy
Generate.hs view
@@ -9,6 +9,7 @@ import System.Directory import Data.Char import Data.Maybe+import Prelude   main :: IO ()
extra.cabal view
@@ -1,7 +1,7 @@ cabal-version:      >= 1.10 build-type:         Simple name:               extra-version:            1.1+version:            1.2 license:            BSD3 license-file:       LICENSE category:           Development@@ -15,7 +15,7 @@     The module "Extra" documents all functions provided by this library. Modules such as "Data.List.Extra" provide extra functions over "Data.List" and also reexport "Data.List". Users are recommended to replace "Data.List" imports with "Data.List.Extra" if they need the extra functionality. homepage:           https://github.com/ndmitchell/extra#readme bug-reports:        https://github.com/ndmitchell/extra/issues-tested-with:        GHC==7.10.1, GHC==7.8.3, GHC==7.6.3, GHC==7.4.2, GHC==7.2.2+tested-with:        GHC==7.10.1, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2, GHC==7.2.2  extra-source-files:     CHANGES.txt
src/Control/Concurrent/Extra.hs view
@@ -15,7 +15,7 @@ module Control.Concurrent.Extra(     module Control.Concurrent,     getNumCapabilities, setNumCapabilities, withNumCapabilities,-    forkFinally, once,+    forkFinally, once, onceFork,     -- * Lock     Lock, newLock, withLock, withLockTry,     -- * Var@@ -73,24 +73,41 @@ #endif  -data Once a = OncePending | OnceRunning (Barrier a) | OnceDone a-- -- | Given an action, produce a wrapped action that runs at most once. --   If the function raises an exception, the same exception will be reraised each time.+--+-- > let x ||| y = do t1 <- onceFork x; t2 <- onceFork y; t1; t2+-- > \(x :: IO Int) -> void (once x) == return ()+-- > \(x :: IO Int) -> join (once x) == x+-- > \(x :: IO Int) -> (do y <- once x; y; y) == x+-- > \(x :: IO Int) -> (do y <- once x; y ||| y) == x once :: IO a -> IO (IO a) once act = do     var <- newVar OncePending-    let run = either throw return-    return $ join $ modifyVar var $ \v -> case v of-        OnceDone x -> return (v, run x)-        OnceRunning x -> return (v, run =<< waitBarrier x)+    let run = either throwIO return+    return $ mask $ \unmask -> join $ modifyVar var $ \v -> case v of+        OnceDone x -> return (v, unmask $ run x)+        OnceRunning x -> return (v, unmask $ run =<< waitBarrier x)         OncePending -> do             b <- newBarrier             return $ (OnceRunning b,) $ do-                res <- try_ act+                res <- try_ $ unmask act+                signalBarrier b res                 modifyVar_ var $ \_ -> return $ OnceDone res                 run res++data Once a = OncePending | OnceRunning (Barrier a) | OnceDone a+++-- | Like 'once', but immediately starts running the computation on a background thread.+--+-- > \(x :: IO Int) -> join (onceFork x) == x+-- > \(x :: IO Int) -> (do a <- onceFork x; a; a) == x+onceFork :: IO a -> IO (IO a)+onceFork act = do+    bar <- newBarrier+    forkFinally act $ signalBarrier bar+    return $ either throwIO return =<< waitBarrier bar   ---------------------------------------------------------------------
src/Extra.hs view
@@ -5,7 +5,7 @@ module Extra(     -- * Control.Concurrent.Extra     -- | Extra functions available in @"Control.Concurrent.Extra"@.-    getNumCapabilities, setNumCapabilities, withNumCapabilities, forkFinally, once, Lock, newLock, withLock, withLockTry, Var, newVar, readVar, modifyVar, modifyVar_, withVar, Barrier, newBarrier, signalBarrier, waitBarrier, waitBarrierMaybe,+    getNumCapabilities, setNumCapabilities, withNumCapabilities, forkFinally, once, onceFork, Lock, newLock, withLock, withLockTry, Var, newVar, readVar, modifyVar, modifyVar_, withVar, Barrier, newBarrier, signalBarrier, waitBarrier, waitBarrierMaybe,     -- * Control.Exception.Extra     -- | Extra functions available in @"Control.Exception.Extra"@.     retry, showException, stringException, ignore, catch_, handle_, try_, catchJust_, handleJust_, tryJust_, catchBool, handleBool, tryBool,
src/System/IO/Extra.hs view
@@ -120,6 +120,7 @@             hDuplicateTo h out             act `finally` do                 hDuplicateTo out2 out+                hClose out2                 hSetBuffering out buf  
test/TestGen.hs view
@@ -4,6 +4,13 @@ default(Maybe Bool,Int,Double,Maybe (Maybe Bool),Maybe (Maybe Char)) tests :: IO () tests = do+    let x ||| y = do t1 <- onceFork x; t2 <- onceFork y; t1; t2+    testGen "\\(x :: IO Int) -> void (once x) == return ()" $ \(x :: IO Int) -> void (once x) == return ()+    testGen "\\(x :: IO Int) -> join (once x) == x" $ \(x :: IO Int) -> join (once x) == x+    testGen "\\(x :: IO Int) -> (do y <- once x; y; y) == x" $ \(x :: IO Int) -> (do y <- once x; y; y) == x+    testGen "\\(x :: IO Int) -> (do y <- once x; y ||| y) == x" $ \(x :: IO Int) -> (do y <- once x; y ||| y) == x+    testGen "\\(x :: IO Int) -> join (onceFork x) == x" $ \(x :: IO Int) -> join (onceFork x) == x+    testGen "\\(x :: IO Int) -> (do a <- onceFork x; a; a) == x" $ \(x :: IO Int) -> (do a <- onceFork x; a; a) == x     testGen "stringException \"test\"                           == return \"test\"" $ stringException "test"                           == return "test"     testGen "stringException (\"test\" ++ undefined)            == return \"test<Exception>\"" $ stringException ("test" ++ undefined)            == return "test<Exception>"     testGen "stringException (\"test\" ++ undefined ++ \"hello\") == return \"test<Exception>\"" $ stringException ("test" ++ undefined ++ "hello") == return "test<Exception>"
test/TestUtil.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE ScopedTypeVariables #-}  module TestUtil(runTests, testGen, erroneous, (====), module X) where @@ -59,6 +60,17 @@         a <- try_ $ captureOutput a         b <- try_ $ captureOutput b         return $ a == b++instance Show (IO a) where+    show _ = "<<IO>>"++instance Arbitrary a => Arbitrary (IO a) where+    arbitrary = do+        (prnt :: Maybe Int, thrw :: Maybe Int, res) <- arbitrary+        return $ do+            whenJust prnt print+            whenJust thrw (fail . show)+            return res  instance Eq SomeException where     a == b = show a == show b