{-# LANGUAGE CPP
, DeriveDataTypeable
, NoImplicitPrelude
, ImpredicativeTypes
, RankNTypes #-}
#if __GLASGOW_HASKELL__ >= 701
{-# LANGUAGE Trustworthy #-}
#endif
module Control.Concurrent.Thread.Group
( ThreadGroup
, new
, nrOfRunning
, wait
, waitN
, forkIO
, forkOS
, forkOn
, forkIOWithUnmask
, forkOnWithUnmask
) where
import qualified Control.Concurrent ( forkOS
, forkIOWithUnmask
, forkOnWithUnmask
)
import Control.Concurrent ( ThreadId )
import Control.Concurrent.MVar ( newEmptyMVar, putMVar, readMVar )
import Control.Exception ( try, mask )
import Control.Monad ( return, (>>=), when )
import Data.Function ( (.), ($) )
import Data.Functor ( fmap )
import Data.Eq ( Eq )
import Data.Ord ( (>=) )
import Data.Int ( Int )
import Data.Typeable ( Typeable )
import Prelude ( ($!), (+), subtract )
import System.IO ( IO )
import Control.Concurrent.STM.TVar ( TVar, newTVarIO, readTVar, writeTVar )
import Control.Concurrent.STM ( STM, atomically, retry )
import Control.Concurrent.Thread ( Result )
import Control.Concurrent.Raw ( rawForkIO, rawForkOn )
#ifdef __HADDOCK_VERSION__
import qualified Control.Concurrent.Thread as Thread ( forkIO
, forkOS
, forkOn
, forkIOWithUnmask
, forkOnWithUnmask
)
#endif
newtype ThreadGroup = ThreadGroup (TVar Int) deriving (ThreadGroup -> ThreadGroup -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ThreadGroup -> ThreadGroup -> Bool
$c/= :: ThreadGroup -> ThreadGroup -> Bool
== :: ThreadGroup -> ThreadGroup -> Bool
$c== :: ThreadGroup -> ThreadGroup -> Bool
Eq, Typeable)
new :: IO ThreadGroup
new :: IO ThreadGroup
new = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap TVar Int -> ThreadGroup
ThreadGroup forall a b. (a -> b) -> a -> b
$ forall a. a -> IO (TVar a)
newTVarIO Int
0
nrOfRunning :: ThreadGroup -> STM Int
nrOfRunning :: ThreadGroup -> STM Int
nrOfRunning (ThreadGroup TVar Int
numThreadsTV) = forall a. TVar a -> STM a
readTVar TVar Int
numThreadsTV
wait :: ThreadGroup -> IO ()
wait :: ThreadGroup -> IO ()
wait = Int -> ThreadGroup -> IO ()
waitN Int
1
waitN :: Int -> ThreadGroup -> IO ()
waitN :: Int -> ThreadGroup -> IO ()
waitN Int
i ThreadGroup
tg = forall a. STM a -> IO a
atomically forall a b. (a -> b) -> a -> b
$ ThreadGroup -> STM Int
nrOfRunning ThreadGroup
tg forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Int
n -> forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
n forall a. Ord a => a -> a -> Bool
>= Int
i) forall a. STM a
retry
forkIO :: ThreadGroup -> IO a -> IO (ThreadId, IO (Result a))
forkIO :: forall a. ThreadGroup -> IO a -> IO (ThreadId, IO (Result a))
forkIO = forall a.
(IO () -> IO ThreadId)
-> ThreadGroup -> IO a -> IO (ThreadId, IO (Result a))
fork IO () -> IO ThreadId
rawForkIO
forkOS :: ThreadGroup -> IO a -> IO (ThreadId, IO (Result a))
forkOS :: forall a. ThreadGroup -> IO a -> IO (ThreadId, IO (Result a))
forkOS = forall a.
(IO () -> IO ThreadId)
-> ThreadGroup -> IO a -> IO (ThreadId, IO (Result a))
fork IO () -> IO ThreadId
Control.Concurrent.forkOS
forkOn :: Int -> ThreadGroup -> IO a -> IO (ThreadId, IO (Result a))
forkOn :: forall a.
Int -> ThreadGroup -> IO a -> IO (ThreadId, IO (Result a))
forkOn = forall a.
(IO () -> IO ThreadId)
-> ThreadGroup -> IO a -> IO (ThreadId, IO (Result a))
fork forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> IO () -> IO ThreadId
rawForkOn
forkIOWithUnmask
:: ThreadGroup
-> ((forall b. IO b -> IO b) -> IO a)
-> IO (ThreadId, IO (Result a))
forkIOWithUnmask :: forall a.
ThreadGroup
-> ((forall b. IO b -> IO b) -> IO a)
-> IO (ThreadId, IO (Result a))
forkIOWithUnmask = forall a.
(((forall b. IO b -> IO b) -> IO ()) -> IO ThreadId)
-> ThreadGroup
-> ((forall b. IO b -> IO b) -> IO a)
-> IO (ThreadId, IO (Result a))
forkWithUnmask ((forall b. IO b -> IO b) -> IO ()) -> IO ThreadId
Control.Concurrent.forkIOWithUnmask
forkOnWithUnmask
:: Int
-> ThreadGroup
-> ((forall b. IO b -> IO b) -> IO a)
-> IO (ThreadId, IO (Result a))
forkOnWithUnmask :: forall a.
Int
-> ThreadGroup
-> ((forall b. IO b -> IO b) -> IO a)
-> IO (ThreadId, IO (Result a))
forkOnWithUnmask = forall a.
(((forall b. IO b -> IO b) -> IO ()) -> IO ThreadId)
-> ThreadGroup
-> ((forall b. IO b -> IO b) -> IO a)
-> IO (ThreadId, IO (Result a))
forkWithUnmask forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ((forall b. IO b -> IO b) -> IO ()) -> IO ThreadId
Control.Concurrent.forkOnWithUnmask
fork :: (IO () -> IO ThreadId)
-> ThreadGroup
-> IO a
-> IO (ThreadId, IO (Result a))
fork :: forall a.
(IO () -> IO ThreadId)
-> ThreadGroup -> IO a -> IO (ThreadId, IO (Result a))
fork IO () -> IO ThreadId
doFork (ThreadGroup TVar Int
numThreadsTV) IO a
a = do
MVar (Result a)
res <- forall a. IO (MVar a)
newEmptyMVar
ThreadId
tid <- forall b. ((forall b. IO b -> IO b) -> IO b) -> IO b
mask forall a b. (a -> b) -> a -> b
$ \forall b. IO b -> IO b
restore -> do
forall a. STM a -> IO a
atomically forall a b. (a -> b) -> a -> b
$ forall a. TVar a -> (a -> a) -> STM ()
modifyTVar TVar Int
numThreadsTV (forall a. Num a => a -> a -> a
+ Int
1)
IO () -> IO ThreadId
doFork forall a b. (a -> b) -> a -> b
$ do
forall e a. Exception e => IO a -> IO (Either e a)
try (forall b. IO b -> IO b
restore IO a
a) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a. MVar a -> a -> IO ()
putMVar MVar (Result a)
res
forall a. STM a -> IO a
atomically forall a b. (a -> b) -> a -> b
$ forall a. TVar a -> (a -> a) -> STM ()
modifyTVar TVar Int
numThreadsTV (forall a. Num a => a -> a -> a
subtract Int
1)
forall (m :: * -> *) a. Monad m => a -> m a
return (ThreadId
tid, forall a. MVar a -> IO a
readMVar MVar (Result a)
res)
forkWithUnmask
:: (((forall b. IO b -> IO b) -> IO ()) -> IO ThreadId)
-> ThreadGroup
-> ((forall b. IO b -> IO b) -> IO a)
-> IO (ThreadId, IO (Result a))
forkWithUnmask :: forall a.
(((forall b. IO b -> IO b) -> IO ()) -> IO ThreadId)
-> ThreadGroup
-> ((forall b. IO b -> IO b) -> IO a)
-> IO (ThreadId, IO (Result a))
forkWithUnmask ((forall b. IO b -> IO b) -> IO ()) -> IO ThreadId
doForkWithUnmask = \(ThreadGroup TVar Int
numThreadsTV) (forall b. IO b -> IO b) -> IO a
f -> do
MVar (Result a)
res <- forall a. IO (MVar a)
newEmptyMVar
ThreadId
tid <- forall b. ((forall b. IO b -> IO b) -> IO b) -> IO b
mask forall a b. (a -> b) -> a -> b
$ \forall b. IO b -> IO b
restore -> do
forall a. STM a -> IO a
atomically forall a b. (a -> b) -> a -> b
$ forall a. TVar a -> (a -> a) -> STM ()
modifyTVar TVar Int
numThreadsTV (forall a. Num a => a -> a -> a
+ Int
1)
((forall b. IO b -> IO b) -> IO ()) -> IO ThreadId
doForkWithUnmask forall a b. (a -> b) -> a -> b
$ \forall b. IO b -> IO b
unmask -> do
forall e a. Exception e => IO a -> IO (Either e a)
try (forall b. IO b -> IO b
restore forall a b. (a -> b) -> a -> b
$ (forall b. IO b -> IO b) -> IO a
f forall b. IO b -> IO b
unmask) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a. MVar a -> a -> IO ()
putMVar MVar (Result a)
res
forall a. STM a -> IO a
atomically forall a b. (a -> b) -> a -> b
$ forall a. TVar a -> (a -> a) -> STM ()
modifyTVar TVar Int
numThreadsTV (forall a. Num a => a -> a -> a
subtract Int
1)
forall (m :: * -> *) a. Monad m => a -> m a
return (ThreadId
tid, forall a. MVar a -> IO a
readMVar MVar (Result a)
res)
modifyTVar :: TVar a -> (a -> a) -> STM ()
modifyTVar :: forall a. TVar a -> (a -> a) -> STM ()
modifyTVar TVar a
tv a -> a
f = forall a. TVar a -> STM a
readTVar TVar a
tv forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a. TVar a -> a -> STM ()
writeTVar TVar a
tv forall b c a. (b -> c) -> (a -> b) -> a -> c
.! a -> a
f
(.!) :: (b -> c) -> (a -> b) -> (a -> c)
b -> c
f .! :: forall b c a. (b -> c) -> (a -> b) -> a -> c
.! a -> b
g = \a
x -> b -> c
f forall a b. (a -> b) -> a -> b
$! a -> b
g a
x