{-# LANGUAGE NamedFieldPuns #-}
module Internal.Finalizer (Cell, get, newCell, addFinalizer) where
import Control.Concurrent.MVar (MVar, mkWeakMVar, newEmptyMVar)
import Control.Concurrent.STM
(STM, TVar, atomically, modifyTVar', newTVar, readTVar)
newtype Cell a
= Cell (TVar (CellData a))
deriving(Cell a -> Cell a -> Bool
(Cell a -> Cell a -> Bool)
-> (Cell a -> Cell a -> Bool) -> Eq (Cell a)
forall a. Cell a -> Cell a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Cell a -> Cell a -> Bool
$c/= :: forall a. Cell a -> Cell a -> Bool
== :: Cell a -> Cell a -> Bool
$c== :: forall a. Cell a -> Cell a -> Bool
Eq)
data CellData a = CellData
{ CellData a -> a
value :: a
, CellData a -> [MVar ()]
finalizers :: [MVar ()]
}
deriving(CellData a -> CellData a -> Bool
(CellData a -> CellData a -> Bool)
-> (CellData a -> CellData a -> Bool) -> Eq (CellData a)
forall a. Eq a => CellData a -> CellData a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CellData a -> CellData a -> Bool
$c/= :: forall a. Eq a => CellData a -> CellData a -> Bool
== :: CellData a -> CellData a -> Bool
$c== :: forall a. Eq a => CellData a -> CellData a -> Bool
Eq)
get :: Cell a -> STM a
get :: Cell a -> STM a
get (Cell TVar (CellData a)
state) = CellData a -> a
forall a. CellData a -> a
value (CellData a -> a) -> STM (CellData a) -> STM a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TVar (CellData a) -> STM (CellData a)
forall a. TVar a -> STM a
readTVar TVar (CellData a)
state
newCell :: a -> STM (Cell a)
newCell :: a -> STM (Cell a)
newCell a
value = TVar (CellData a) -> Cell a
forall a. TVar (CellData a) -> Cell a
Cell (TVar (CellData a) -> Cell a)
-> STM (TVar (CellData a)) -> STM (Cell a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CellData a -> STM (TVar (CellData a))
forall a. a -> STM (TVar a)
newTVar CellData :: forall a. a -> [MVar ()] -> CellData a
CellData { a
value :: a
value :: a
value, finalizers :: [MVar ()]
finalizers = [] }
addFinalizer :: Cell a -> STM () -> IO ()
addFinalizer :: Cell a -> STM () -> IO ()
addFinalizer (Cell TVar (CellData a)
stateVar) STM ()
fin = do
MVar ()
mvar <- IO (MVar ())
forall a. IO (MVar a)
newEmptyMVar
Weak (MVar ())
_ <- MVar () -> IO () -> IO (Weak (MVar ()))
forall a. MVar a -> IO () -> IO (Weak (MVar a))
mkWeakMVar MVar ()
mvar (IO () -> IO (Weak (MVar ()))) -> IO () -> IO (Weak (MVar ()))
forall a b. (a -> b) -> a -> b
$ STM () -> IO ()
forall a. STM a -> IO a
atomically STM ()
fin
STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ TVar (CellData a) -> (CellData a -> CellData a) -> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar (CellData a)
stateVar ((CellData a -> CellData a) -> STM ())
-> (CellData a -> CellData a) -> STM ()
forall a b. (a -> b) -> a -> b
$ \state :: CellData a
state@CellData{[MVar ()]
finalizers :: [MVar ()]
finalizers :: forall a. CellData a -> [MVar ()]
finalizers} ->
CellData a
state { finalizers :: [MVar ()]
finalizers = MVar ()
mvar MVar () -> [MVar ()] -> [MVar ()]
forall a. a -> [a] -> [a]
: [MVar ()]
finalizers }