{-# LANGUAGE ScopedTypeVariables #-}
module Data.Array.Accelerate.LLVM.PTX.Pool (
Pool,
create, with, take, put,
unsafeWith,
) where
import Control.Concurrent.MVar
import Control.Exception
import Data.Maybe
import System.IO.Unsafe
import Prelude hiding ( take )
import Data.Sequence ( Seq )
import qualified Data.Sequence as Seq
data Pool a = Pool {-# UNPACK #-} !(MVar ([a], Seq (MVar a)))
create :: [a] -> IO (Pool a)
create :: [a] -> IO (Pool a)
create [a]
initial =
MVar ([a], Seq (MVar a)) -> Pool a
forall a. MVar ([a], Seq (MVar a)) -> Pool a
Pool (MVar ([a], Seq (MVar a)) -> Pool a)
-> IO (MVar ([a], Seq (MVar a))) -> IO (Pool a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ([a], Seq (MVar a)) -> IO (MVar ([a], Seq (MVar a)))
forall a. a -> IO (MVar a)
newMVar ([a]
initial, Seq (MVar a)
forall a. Seq a
Seq.empty)
with :: Pool a -> (a -> IO b) -> IO b
with :: Pool a -> (a -> IO b) -> IO b
with Pool a
pool a -> IO b
action =
IO a -> (a -> IO ()) -> (a -> IO b) -> IO b
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket (Pool a -> IO a
forall a. Pool a -> IO a
take Pool a
pool) (Pool a -> a -> IO ()
forall a. Pool a -> a -> IO ()
put Pool a
pool) a -> IO b
action
unsafeWith :: Pool a -> (a -> b) -> b
unsafeWith :: Pool a -> (a -> b) -> b
unsafeWith Pool a
pool a -> b
action =
IO b -> b
forall a. IO a -> a
unsafePerformIO (IO b -> b) -> IO b -> b
forall a b. (a -> b) -> a -> b
$ Pool a -> (a -> IO b) -> IO b
forall a b. Pool a -> (a -> IO b) -> IO b
with Pool a
pool (b -> IO b
forall a. a -> IO a
evaluate (b -> IO b) -> (a -> b) -> a -> IO b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
action)
take :: Pool a -> IO a
take :: Pool a -> IO a
take (Pool MVar ([a], Seq (MVar a))
ref) =
IO a -> IO a
forall a. IO a -> IO a
mask_ (IO a -> IO a) -> IO a -> IO a
forall a b. (a -> b) -> a -> b
$ do
([a]
r, Seq (MVar a)
bs) <- MVar ([a], Seq (MVar a)) -> IO ([a], Seq (MVar a))
forall a. MVar a -> IO a
takeMVar MVar ([a], Seq (MVar a))
ref
case [a]
r of
[] -> do
MVar a
b <- IO (MVar a)
forall a. IO (MVar a)
newEmptyMVar
MVar ([a], Seq (MVar a)) -> ([a], Seq (MVar a)) -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar ([a], Seq (MVar a))
ref ([a]
r, Seq (MVar a)
bs Seq (MVar a) -> MVar a -> Seq (MVar a)
forall a. Seq a -> a -> Seq a
Seq.|> MVar a
b)
MVar a -> IO a
wait MVar a
b
(a
a:[a]
as) -> do
MVar ([a], Seq (MVar a)) -> ([a], Seq (MVar a)) -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar ([a], Seq (MVar a))
ref ([a]
as, Seq (MVar a)
bs)
a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
where
wait :: MVar a -> IO a
wait MVar a
b =
MVar a -> IO a
forall a. MVar a -> IO a
takeMVar MVar a
b IO a -> (SomeException -> IO a) -> IO a
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`catch` \(SomeException
e :: SomeException) ->
IO a -> IO a
forall a. IO a -> IO a
uninterruptibleMask_ (IO a -> IO a) -> IO a -> IO a
forall a b. (a -> b) -> a -> b
$ do
([a], Seq (MVar a))
r <- MVar ([a], Seq (MVar a)) -> IO ([a], Seq (MVar a))
forall a. MVar a -> IO a
takeMVar MVar ([a], Seq (MVar a))
ref
Maybe a
ma <- MVar a -> IO (Maybe a)
forall a. MVar a -> IO (Maybe a)
tryTakeMVar MVar a
b
([a], Seq (MVar a))
r' <- case Maybe a
ma of
Just a
a -> a -> ([a], Seq (MVar a)) -> IO ([a], Seq (MVar a))
forall a. a -> ([a], Seq (MVar a)) -> IO ([a], Seq (MVar a))
signal a
a ([a], Seq (MVar a))
r
Maybe a
Nothing -> do MVar a -> a -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar a
b (SomeException -> a
forall a e. Exception e => e -> a
throw SomeException
e)
([a], Seq (MVar a)) -> IO ([a], Seq (MVar a))
forall (m :: * -> *) a. Monad m => a -> m a
return ([a], Seq (MVar a))
r
MVar ([a], Seq (MVar a)) -> ([a], Seq (MVar a)) -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar ([a], Seq (MVar a))
ref ([a], Seq (MVar a))
r'
SomeException -> IO a
forall e a. Exception e => e -> IO a
throwIO SomeException
e
put :: Pool a -> a -> IO ()
put :: Pool a -> a -> IO ()
put (Pool MVar ([a], Seq (MVar a))
ref) a
a =
IO () -> IO ()
forall a. IO a -> IO a
uninterruptibleMask_ (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
([a], Seq (MVar a))
r <- MVar ([a], Seq (MVar a)) -> IO ([a], Seq (MVar a))
forall a. MVar a -> IO a
takeMVar MVar ([a], Seq (MVar a))
ref
([a], Seq (MVar a))
r' <- a -> ([a], Seq (MVar a)) -> IO ([a], Seq (MVar a))
forall a. a -> ([a], Seq (MVar a)) -> IO ([a], Seq (MVar a))
signal a
a ([a], Seq (MVar a))
r
MVar ([a], Seq (MVar a)) -> ([a], Seq (MVar a)) -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar ([a], Seq (MVar a))
ref ([a], Seq (MVar a))
r'
signal :: a -> ([a], Seq (MVar a)) -> IO ([a], Seq (MVar a))
signal :: a -> ([a], Seq (MVar a)) -> IO ([a], Seq (MVar a))
signal a
a ([a]
as, Seq (MVar a)
blocked) =
if [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [a]
as
then Seq (MVar a) -> IO ([a], Seq (MVar a))
loop Seq (MVar a)
blocked
else ([a], Seq (MVar a)) -> IO ([a], Seq (MVar a))
forall (m :: * -> *) a. Monad m => a -> m a
return (a
aa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
as, Seq (MVar a)
blocked)
where
loop :: Seq (MVar a) -> IO ([a], Seq (MVar a))
loop Seq (MVar a)
blocked' =
case Seq (MVar a) -> ViewL (MVar a)
forall a. Seq a -> ViewL a
Seq.viewl Seq (MVar a)
blocked' of
ViewL (MVar a)
Seq.EmptyL -> ([a], Seq (MVar a)) -> IO ([a], Seq (MVar a))
forall (m :: * -> *) a. Monad m => a -> m a
return ([a
a], Seq (MVar a)
forall a. Seq a
Seq.empty)
MVar a
b Seq.:< Seq (MVar a)
bs -> do
Bool
r <- MVar a -> a -> IO Bool
forall a. MVar a -> a -> IO Bool
tryPutMVar MVar a
b a
a
if Bool
r then ([a], Seq (MVar a)) -> IO ([a], Seq (MVar a))
forall (m :: * -> *) a. Monad m => a -> m a
return ([], Seq (MVar a)
bs)
else Seq (MVar a) -> IO ([a], Seq (MVar a))
loop Seq (MVar a)
bs