module Data.CBRef
( CBRef
, newCBRef
, readCBRef
, writeCBRef
, modifyCBRef
, atomicModifyCBRef
, installCallbackCBRef
)
where
import Data.IORef
data CBRef a = CBRef (IORef (a, [IO ()]))
newCBRef :: a -> IO (CBRef a)
newCBRef v = fmap CBRef $ newIORef (v,[])
readCBRef :: CBRef a -> IO a
readCBRef (CBRef ref) = fmap fst $ readIORef ref
writeCBRef :: CBRef a -> a -> IO ()
writeCBRef (CBRef ref) v = do
modifyIORef ref (\(_,cb) -> (v,cb))
runCallbacks ref
runCallbacks :: IORef (a, [IO ()]) -> IO ()
runCallbacks ref = (sequence_.snd) =<< readIORef ref
modifyCBRef :: CBRef a -> (a -> a) -> IO ()
modifyCBRef (CBRef ref) f = do
modifyIORef ref (\(v,cb) -> (f v,cb))
runCallbacks ref
atomicModifyCBRef :: CBRef a -> (a -> (a, b)) -> IO b
atomicModifyCBRef (CBRef ref) f = do
v <- atomicModifyIORef ref modifier
runCallbacks ref
return v
where modifier (v,cb) = let (v', r) = f v in ((v',cb), r)
installCallbackCBRef :: CBRef a -> IO () -> IO ()
installCallbackCBRef (CBRef ref) p =
modifyIORef ref (\(v,cb) -> (v,cb ++ [p]))