module Streamly.Internal.Data.IOFinalizer
(
IOFinalizer(..)
, newIOFinalizer
, runIOFinalizer
, clearingIOFinalizer
)
where
import Control.Exception (mask_)
import Control.Monad (void)
import Control.Monad.IO.Class (MonadIO(..))
import Data.IORef (newIORef, readIORef, mkWeakIORef, writeIORef, IORef)
newtype IOFinalizer = IOFinalizer (IORef (Maybe (IO ())))
runFinalizerGC :: IORef (Maybe (IO ())) -> IO ()
runFinalizerGC :: IORef (Maybe (IO ())) -> IO ()
runFinalizerGC IORef (Maybe (IO ()))
ref = do
Maybe (IO ())
res <- forall a. IORef a -> IO a
readIORef IORef (Maybe (IO ()))
ref
case Maybe (IO ())
res of
Maybe (IO ())
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just IO ()
f -> IO ()
f
newIOFinalizer :: MonadIO m => IO a -> m IOFinalizer
newIOFinalizer :: forall (m :: * -> *) a. MonadIO m => IO a -> m IOFinalizer
newIOFinalizer IO a
finalizer = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ do
let f :: IO ()
f = forall (f :: * -> *) a. Functor f => f a -> f ()
void IO a
finalizer
IORef (Maybe (IO ()))
ref <- forall a. a -> IO (IORef a)
newIORef forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just IO ()
f
Weak (IORef (Maybe (IO ())))
_ <- forall a. IORef a -> IO () -> IO (Weak (IORef a))
mkWeakIORef IORef (Maybe (IO ()))
ref (IORef (Maybe (IO ())) -> IO ()
runFinalizerGC IORef (Maybe (IO ()))
ref)
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ IORef (Maybe (IO ())) -> IOFinalizer
IOFinalizer IORef (Maybe (IO ()))
ref
runIOFinalizer :: MonadIO m => IOFinalizer -> m ()
runIOFinalizer :: forall (m :: * -> *). MonadIO m => IOFinalizer -> m ()
runIOFinalizer (IOFinalizer IORef (Maybe (IO ()))
ref) = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ do
Maybe (IO ())
res <- forall a. IORef a -> IO a
readIORef IORef (Maybe (IO ()))
ref
case Maybe (IO ())
res of
Maybe (IO ())
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just IO ()
action -> do
forall a. IO a -> IO a
mask_ forall a b. (a -> b) -> a -> b
$ do
forall a. IORef a -> a -> IO ()
writeIORef IORef (Maybe (IO ()))
ref forall a. Maybe a
Nothing
IO ()
action
clearingIOFinalizer :: MonadIO m => IOFinalizer -> IO a -> m a
clearingIOFinalizer :: forall (m :: * -> *) a. MonadIO m => IOFinalizer -> IO a -> m a
clearingIOFinalizer (IOFinalizer IORef (Maybe (IO ()))
ref) IO a
action = do
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall a. IO a -> IO a
mask_ forall a b. (a -> b) -> a -> b
$ do
Maybe (IO ())
res <- forall a. IORef a -> IO a
readIORef IORef (Maybe (IO ()))
ref
case Maybe (IO ())
res of
Just IO ()
_ -> do
forall a. IORef a -> a -> IO ()
writeIORef IORef (Maybe (IO ()))
ref forall a. Maybe a
Nothing
IO a
action
Maybe (IO ())
Nothing -> forall a. HasCallStack => [Char] -> a
error [Char]
"clearingIOFinalizer: finalizer not set"