{-# LANGUAGE CPP #-}
module Streamly.Internal.Control.Exception
(
verify
, verifyM
, AcquireIO(..)
, Priority(..)
, allocator
, releaser
, withAcquireIO
, acquireWith
, acquire
, acquire_
, registerWith
, register
, hook
)
where
import Control.Monad (void)
import Control.Monad.IO.Class (MonadIO(..))
import Control.Exception (mask_)
import Control.Monad.Catch (MonadMask)
import Data.IntMap.Strict (IntMap)
import Data.IORef (IORef, newIORef, atomicModifyIORef')
import qualified Control.Monad.Catch as MC
import qualified Data.IntMap.Strict as Map
#include "DocTestControlException.hs"
{-# INLINE verify #-}
verify :: Bool -> a -> a
verify :: forall a. Bool -> a -> a
verify Bool
predicate a
val =
if Bool
predicate
then [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"verify failed"
else a
val
{-# INLINE verifyM #-}
verifyM :: Applicative f => Bool -> f ()
verifyM :: forall (f :: * -> *). Applicative f => Bool -> f ()
verifyM Bool
predicate = Bool -> f () -> f ()
forall a. Bool -> a -> a
verify Bool
predicate (() -> f ()
forall a. a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())
data Priority = Priority1 | Priority2 deriving Int -> Priority -> ShowS
[Priority] -> ShowS
Priority -> [Char]
(Int -> Priority -> ShowS)
-> (Priority -> [Char]) -> ([Priority] -> ShowS) -> Show Priority
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Priority -> ShowS
showsPrec :: Int -> Priority -> ShowS
$cshow :: Priority -> [Char]
show :: Priority -> [Char]
$cshowList :: [Priority] -> ShowS
showList :: [Priority] -> ShowS
Show
newtype AcquireIO = AcquireIO
(forall b c. Priority -> IO b -> (b -> IO c) -> IO (b, IO ()))
allocator :: MonadIO m =>
IORef (Int, IntMap (IO ()), IntMap (IO ()))
-> Priority
-> IO a
-> (a -> IO b)
-> m (a, m ())
allocator :: forall (m :: * -> *) a b.
MonadIO m =>
IORef (Int, IntMap (IO ()), IntMap (IO ()))
-> Priority -> IO a -> (a -> IO b) -> m (a, m ())
allocator IORef (Int, IntMap (IO ()), IntMap (IO ()))
ref Priority
pri IO a
alloc a -> IO b
free = do
let insertResource :: a
-> (Int, IntMap (IO ()), IntMap (IO ()))
-> ((Int, IntMap (IO ()), IntMap (IO ())), Int)
insertResource a
r (Int
i, IntMap (IO ())
mp1, IntMap (IO ())
mp2) =
case Priority
pri of
Priority
Priority1 ->
((Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1, Int -> IO () -> IntMap (IO ()) -> IntMap (IO ())
forall a. Int -> a -> IntMap a -> IntMap a
Map.insert Int
i (IO b -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO b -> IO ()) -> IO b -> IO ()
forall a b. (a -> b) -> a -> b
$ a -> IO b
free a
r) IntMap (IO ())
mp1, IntMap (IO ())
mp2), Int
i)
Priority
Priority2 ->
((Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1, IntMap (IO ())
mp1, Int -> IO () -> IntMap (IO ()) -> IntMap (IO ())
forall a. Int -> a -> IntMap a -> IntMap a
Map.insert Int
i (IO b -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO b -> IO ()) -> IO b -> IO ()
forall a b. (a -> b) -> a -> b
$ a -> IO b
free a
r) IntMap (IO ())
mp2), Int
i)
(a
r, Int
index) <-
IO (a, Int) -> m (a, Int)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (a, Int) -> m (a, Int)) -> IO (a, Int) -> m (a, Int)
forall a b. (a -> b) -> a -> b
$ IO (a, Int) -> IO (a, Int)
forall a. IO a -> IO a
mask_ (IO (a, Int) -> IO (a, Int)) -> IO (a, Int) -> IO (a, Int)
forall a b. (a -> b) -> a -> b
$ do
a
r <- IO a
alloc
Int
idx <- IORef (Int, IntMap (IO ()), IntMap (IO ()))
-> ((Int, IntMap (IO ()), IntMap (IO ()))
-> ((Int, IntMap (IO ()), IntMap (IO ())), Int))
-> IO Int
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef (Int, IntMap (IO ()), IntMap (IO ()))
ref (a
-> (Int, IntMap (IO ()), IntMap (IO ()))
-> ((Int, IntMap (IO ()), IntMap (IO ())), Int)
insertResource a
r)
(a, Int) -> IO (a, Int)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
r, Int
idx)
let deleteResource :: (a, IntMap a, IntMap a) -> ((a, IntMap a, IntMap a), Maybe a)
deleteResource (a
i, IntMap a
mp1, IntMap a
mp2) =
case Priority
pri of
Priority
Priority1 ->
let res :: Maybe a
res = Int -> IntMap a -> Maybe a
forall a. Int -> IntMap a -> Maybe a
Map.lookup Int
index IntMap a
mp1
in ((a
i, Int -> IntMap a -> IntMap a
forall a. Int -> IntMap a -> IntMap a
Map.delete Int
index IntMap a
mp1, IntMap a
mp2), Maybe a
res)
Priority
Priority2 ->
let res :: Maybe a
res = Int -> IntMap a -> Maybe a
forall a. Int -> IntMap a -> Maybe a
Map.lookup Int
index IntMap a
mp2
in ((a
i, IntMap a
mp1, Int -> IntMap a -> IntMap a
forall a. Int -> IntMap a -> IntMap a
Map.delete Int
index IntMap a
mp2), Maybe a
res)
release :: m ()
release =
IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ IO () -> IO ()
forall a. IO a -> IO a
mask_ (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Maybe (IO ())
f <- IORef (Int, IntMap (IO ()), IntMap (IO ()))
-> ((Int, IntMap (IO ()), IntMap (IO ()))
-> ((Int, IntMap (IO ()), IntMap (IO ())), Maybe (IO ())))
-> IO (Maybe (IO ()))
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef (Int, IntMap (IO ()), IntMap (IO ()))
ref (Int, IntMap (IO ()), IntMap (IO ()))
-> ((Int, IntMap (IO ()), IntMap (IO ())), Maybe (IO ()))
forall {a} {a}.
(a, IntMap a, IntMap a) -> ((a, IntMap a, IntMap a), Maybe a)
deleteResource
Maybe (IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ Maybe (IO ())
f
(a, m ()) -> m (a, m ())
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
r, m ()
release)
releaser :: MonadIO m => IORef (a, IntMap (IO b), IntMap (IO b)) -> m ()
releaser :: forall (m :: * -> *) a b.
MonadIO m =>
IORef (a, IntMap (IO b), IntMap (IO b)) -> m ()
releaser IORef (a, IntMap (IO b), IntMap (IO b))
ref =
IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ IO () -> IO ()
forall a. IO a -> IO a
mask_ (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
IntMap (IO b)
mp1 <- IORef (a, IntMap (IO b), IntMap (IO b))
-> ((a, IntMap (IO b), IntMap (IO b))
-> ((a, IntMap (IO b), IntMap (IO b)), IntMap (IO b)))
-> IO (IntMap (IO b))
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef (a, IntMap (IO b), IntMap (IO b))
ref
(\(a
i, IntMap (IO b)
mp1,IntMap (IO b)
mp2) -> ((a
i, IntMap (IO b)
forall a. IntMap a
Map.empty, IntMap (IO b)
mp2), IntMap (IO b)
mp1))
IntMap (IO b) -> IO ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ IntMap (IO b)
mp1
IntMap (IO b)
mp2 <- IORef (a, IntMap (IO b), IntMap (IO b))
-> ((a, IntMap (IO b), IntMap (IO b))
-> ((a, IntMap (IO b), IntMap (IO b)), IntMap (IO b)))
-> IO (IntMap (IO b))
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef (a, IntMap (IO b), IntMap (IO b))
ref
(\(a
i, IntMap (IO b)
mp,IntMap (IO b)
mp2) -> ((a
i, IntMap (IO b)
mp, IntMap (IO b)
forall a. IntMap a
Map.empty), IntMap (IO b)
mp2))
IntMap (IO b) -> IO ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ IntMap (IO b)
mp2
{-# INLINE withAcquireIO #-}
withAcquireIO :: (MonadIO m, MonadMask m) => (AcquireIO -> m a) -> m a
withAcquireIO :: forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
(AcquireIO -> m a) -> m a
withAcquireIO AcquireIO -> m a
action = do
IORef (Int, IntMap (IO ()), IntMap (IO ()))
ref <- IO (IORef (Int, IntMap (IO ()), IntMap (IO ())))
-> m (IORef (Int, IntMap (IO ()), IntMap (IO ())))
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (IORef (Int, IntMap (IO ()), IntMap (IO ())))
-> m (IORef (Int, IntMap (IO ()), IntMap (IO ()))))
-> IO (IORef (Int, IntMap (IO ()), IntMap (IO ())))
-> m (IORef (Int, IntMap (IO ()), IntMap (IO ())))
forall a b. (a -> b) -> a -> b
$ (Int, IntMap (IO ()), IntMap (IO ()))
-> IO (IORef (Int, IntMap (IO ()), IntMap (IO ())))
forall a. a -> IO (IORef a)
newIORef (Int
0 :: Int, IntMap (IO ())
forall a. IntMap a
Map.empty, IntMap (IO ())
forall a. IntMap a
Map.empty)
AcquireIO -> m a
action ((forall b c. Priority -> IO b -> (b -> IO c) -> IO (b, IO ()))
-> AcquireIO
AcquireIO (IORef (Int, IntMap (IO ()), IntMap (IO ()))
-> Priority -> IO b -> (b -> IO c) -> IO (b, IO ())
forall (m :: * -> *) a b.
MonadIO m =>
IORef (Int, IntMap (IO ()), IntMap (IO ()))
-> Priority -> IO a -> (a -> IO b) -> m (a, m ())
allocator IORef (Int, IntMap (IO ()), IntMap (IO ()))
ref)) m a -> m () -> m a
forall (m :: * -> *) a b.
(HasCallStack, MonadMask m) =>
m a -> m b -> m a
`MC.finally` IORef (Int, IntMap (IO ()), IntMap (IO ())) -> m ()
forall (m :: * -> *) a b.
MonadIO m =>
IORef (a, IntMap (IO b), IntMap (IO b)) -> m ()
releaser IORef (Int, IntMap (IO ()), IntMap (IO ()))
ref
{-# INLINE acquireWith #-}
acquireWith :: Priority -> AcquireIO -> IO b -> (b -> IO c) -> IO (b, IO ())
acquireWith :: forall b c.
Priority -> AcquireIO -> IO b -> (b -> IO c) -> IO (b, IO ())
acquireWith Priority
pri (AcquireIO forall b c. Priority -> IO b -> (b -> IO c) -> IO (b, IO ())
f) = Priority -> IO b -> (b -> IO c) -> IO (b, IO ())
forall b c. Priority -> IO b -> (b -> IO c) -> IO (b, IO ())
f Priority
pri
acquire :: AcquireIO -> IO b -> (b -> IO c) -> IO (b, IO ())
acquire :: forall b c. AcquireIO -> IO b -> (b -> IO c) -> IO (b, IO ())
acquire = Priority -> AcquireIO -> IO b -> (b -> IO c) -> IO (b, IO ())
forall b c.
Priority -> AcquireIO -> IO b -> (b -> IO c) -> IO (b, IO ())
acquireWith Priority
Priority2
acquire_ :: AcquireIO -> IO b -> (b -> IO c) -> IO b
acquire_ :: forall b c. AcquireIO -> IO b -> (b -> IO c) -> IO b
acquire_ AcquireIO
a IO b
b b -> IO c
c = ((b, IO ()) -> b) -> IO (b, IO ()) -> IO b
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (b, IO ()) -> b
forall a b. (a, b) -> a
fst (IO (b, IO ()) -> IO b) -> IO (b, IO ()) -> IO b
forall a b. (a -> b) -> a -> b
$ AcquireIO -> IO b -> (b -> IO c) -> IO (b, IO ())
forall b c. AcquireIO -> IO b -> (b -> IO c) -> IO (b, IO ())
acquire AcquireIO
a IO b
b b -> IO c
c
{-# INLINE registerWith #-}
registerWith :: Priority -> AcquireIO -> IO () -> IO ()
registerWith :: Priority -> AcquireIO -> IO () -> IO ()
registerWith Priority
pri (AcquireIO forall b c. Priority -> IO b -> (b -> IO c) -> IO (b, IO ())
f) IO ()
g = IO ((), IO ()) -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO ((), IO ()) -> IO ()) -> IO ((), IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ Priority -> IO () -> (() -> IO ()) -> IO ((), IO ())
forall b c. Priority -> IO b -> (b -> IO c) -> IO (b, IO ())
f Priority
pri (() -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()) (\() -> IO ()
g)
register :: AcquireIO -> IO () -> IO ()
register :: AcquireIO -> IO () -> IO ()
register = Priority -> AcquireIO -> IO () -> IO ()
registerWith Priority
Priority2
hook :: AcquireIO -> IO () -> IO (IO())
hook :: AcquireIO -> IO () -> IO (IO ())
hook (AcquireIO forall b c. Priority -> IO b -> (b -> IO c) -> IO (b, IO ())
f) IO ()
g = (((), IO ()) -> IO ()) -> IO ((), IO ()) -> IO (IO ())
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((), IO ()) -> IO ()
forall a b. (a, b) -> b
snd (IO ((), IO ()) -> IO (IO ())) -> IO ((), IO ()) -> IO (IO ())
forall a b. (a -> b) -> a -> b
$ Priority -> IO () -> (() -> IO ()) -> IO ((), IO ())
forall b c. Priority -> IO b -> (b -> IO c) -> IO (b, IO ())
f Priority
Priority2 (() -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()) (\() -> IO ()
g)