module Cgm.Control.Concurrent.NotificationCount (
NotificationCount,
withNotificationCount,
notifying
) where
import Data.Word
import Control.Concurrent
import Control.Applicative
import Control.Arrow
type NotificationCount = MVar (Word64, [IO ()])
mkNotificationCount :: IO NotificationCount
mkNotificationCount = newMVar (0, [])
requireNotify :: NotificationCount -> IO ()
requireNotify = flip modifyMVar_ $ return . first (+ 1)
notify :: NotificationCount -> IO ()
notify = flip modifyMVar_ $ \(n, ios) -> if n == 1 then const (0,[]) <$> sequence_ ios else return (n 1, ios)
whenFullyNotified :: IO () -> NotificationCount -> IO ()
whenFullyNotified io = flip modifyMVar_ $ \s@(n, ios) -> if n == 0 then const s <$> io else return (n, io : ios)
withNotificationCount :: (NotificationCount -> IO a) -> IO () -> IO a
withNotificationCount f k = mkNotificationCount >>= \n -> f n >>= (<$ whenFullyNotified k n)
notifying :: NotificationCount -> (IO () -> IO a) -> IO a
notifying n kf = requireNotify n >> kf (notify n)