module Data.CBMVar ( CBMVar , newCBMVar , readCBMVar , writeCBMVar , modifyCBMVar , installCallbackCBMVar ) where import Control.Concurrent.MVar data CBMVar a = CBMVar (MVar (a, [IO ()])) newCBMVar :: a -> IO (CBMVar a) newCBMVar v = fmap CBMVar $ newMVar (v,[]) readCBMVar :: CBMVar a -> IO a readCBMVar (CBMVar ref) = fmap fst $ readMVar ref writeCBMVar :: CBMVar a -> a -> IO () writeCBMVar (CBMVar ref) v = do modifyMVar_ ref (\(_,cb) -> return (v,cb)) runCallbacks ref runCallbacks :: MVar (a, [IO ()]) -> IO () runCallbacks ref = (sequence_.snd) =<< readMVar ref modifyCBMVar :: CBMVar a -> (a -> IO a) -> IO () modifyCBMVar (CBMVar ref) f = do modifyMVar_ ref (\(v,cb) -> f v >>= \v' -> return (v',cb)) runCallbacks ref installCallbackCBMVar :: CBMVar a -> IO () -> IO () installCallbackCBMVar (CBMVar ref) p = modifyMVar_ ref (\(v,cb) -> return (v,cb ++ [p]))