packages feed

slave-thread 1.0.2.4 → 1.0.2.5

raw patch · 3 files changed

+21/−17 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

library/SlaveThread.hs view
@@ -1,5 +1,5 @@ -- |--- Vanilla thread management in Haskell is low level and +-- Vanilla thread management in Haskell is low level and -- it does not approach the problems related to thread deaths. -- When it's used naively the following typical problems arise: --@@ -22,13 +22,13 @@ -- it kills all the slave threads that were forked from it. -- This protects you from ghost threads. ----- 2. It waits for all slaves to die and execute their finalizers +-- 2. It waits for all slaves to die and execute their finalizers -- before executing its own finalizer and getting released itself. -- This gives you hierarchical releasing of resources. -- -- 3. When a slave thread dies with an uncaught exception -- it reraises it in the master thread.--- This protects you from silent exceptions +-- This protects you from silent exceptions -- and lets you be sure of getting informed -- if your program gets brought to an erroneous state. module SlaveThread@@ -49,7 +49,7 @@ import Control.Monad.Trans.Reader import GHC.Conc import GHC.Exts (Int(I#), fork#, forkOn#)-import GHC.IO (IO(IO))+import GHC.IO (IO(IO), unsafeUnmask) import System.IO.Unsafe import qualified DeferredFolds.UnfoldlM as UnfoldlM import qualified PartialHandler@@ -75,19 +75,19 @@ -- Fork a slave thread with a finalizer action to run a computation on. -- The finalizer gets executed when the thread dies for whatever reason: -- due to being killed or an uncaught exception, or a normal termination.--- +-- -- Note the order of arguments:--- +-- -- >forkFinally finalizer computation {-# INLINABLE forkFinally #-} forkFinally :: IO a -> IO b -> IO ThreadId forkFinally finalizer computation =-  mask $ \unmask -> do+  mask_ $ do     masterThread <- myThreadId     -- Ensures that the thread gets registered before being unregistered     registrationGate <- newEmptyMVar     slaveThread <--      forkIOWithoutHandler $ do+      forkIOWithUnmaskWithoutHandler $ \unmask -> do         slaveThread <- myThreadId         catch           (unmask (void computation))@@ -122,9 +122,9 @@     unless null retry  -- |--- A more efficient version of 'forkIO', +-- A more efficient version of 'forkIOWithUnmask', -- which does not install a default exception handler on the forked thread.-{-# INLINE forkIOWithoutHandler #-}-forkIOWithoutHandler :: IO () -> IO ThreadId-forkIOWithoutHandler action = -  IO $ \s -> case (fork# action s) of (# s', tid #) -> (# s', ThreadId tid #)+{-# INLINE forkIOWithUnmaskWithoutHandler #-}+forkIOWithUnmaskWithoutHandler :: ((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId+forkIOWithUnmaskWithoutHandler action =+  IO $ \s -> case (fork# (action unsafeUnmask)  s) of (# s', tid #) -> (# s', ThreadId tid #)
slave-thread.cabal view
@@ -1,5 +1,5 @@ name: slave-thread-version: 1.0.2.4+version: 1.0.2.5 synopsis: A fundamental solution to ghost threads and silent exceptions description:   Vanilla thread management in Haskell is low level and 
test/Main.hs view
@@ -1,7 +1,6 @@ module Main where  import Prelude-import Control.Concurrent.STM import Test.QuickCheck.Instances import Test.Tasty import Test.Tasty.Runners@@ -124,6 +123,11 @@         takeMVar ready         killThread thread         assertEqual "First finalizer is not slave" 0 =<< atomically (readTMVar var)+    ,+    testCase "Forked threads don't inherit the masking state" $ do+      var <- newEmptyMVar+      mask_ (S.fork (getMaskingState >>= putMVar var))+      assertEqual "" Unmasked =<< takeMVar var   ]  forkWait :: IO a -> IO (IO ())@@ -131,7 +135,7 @@   do     v <- newEmptyMVar     S.fork $ do-      r <- try io+      r <- try @SomeException io       putMVar v ()-      either (throwIO @SomeException) return r+      either throwIO return r     return $ takeMVar v