module Unison.LSP.Util.Signal
( newSignalIO,
writeSignal,
writeSignalIO,
subscribe,
Signal,
)
where
import Control.Monad.STM qualified as STM
import Unison.Prelude
import UnliftIO.STM
newtype Signal a = Signal (TVar (Maybe a, Int))
newSignalIO :: (MonadIO m) => Maybe a -> m (Signal a)
newSignalIO :: forall (m :: * -> *) a. MonadIO m => Maybe a -> m (Signal a)
newSignalIO Maybe a
a = do
tvar <- (Maybe a, Int) -> m (TVar (Maybe a, Int))
forall (m :: * -> *) a. MonadIO m => a -> m (TVar a)
newTVarIO (Maybe a
a, Int
0)
pure (Signal tvar)
writeSignal :: Signal a -> a -> STM ()
writeSignal :: forall a. Signal a -> a -> STM ()
writeSignal (Signal TVar (Maybe a, Int)
signalVar) a
a = do
(_, !n) <- TVar (Maybe a, Int) -> STM (Maybe a, Int)
forall a. TVar a -> STM a
readTVar TVar (Maybe a, Int)
signalVar
writeTVar signalVar (Just a, succ n)
writeSignalIO :: (MonadIO m) => Signal a -> a -> m ()
writeSignalIO :: forall (m :: * -> *) a. MonadIO m => Signal a -> a -> m ()
writeSignalIO Signal a
signal a
a = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ STM () -> IO ()
forall a. STM a -> IO a
STM.atomically (Signal a -> a -> STM ()
forall a. Signal a -> a -> STM ()
writeSignal Signal a
signal a
a)
subscribe :: (MonadIO m) => Signal a -> m (STM a)
subscribe :: forall (m :: * -> *) a. MonadIO m => Signal a -> m (STM a)
subscribe (Signal TVar (Maybe a, Int)
signalVar) = do
(_, !n) <- TVar (Maybe a, Int) -> m (Maybe a, Int)
forall (m :: * -> *) a. MonadIO m => TVar a -> m a
readTVarIO TVar (Maybe a, Int)
signalVar
latestNVar <- newTVarIO (pred n)
pure $ do
(mayA, newN) <- readTVar signalVar
latestN <- readTVar latestNVar
guard (newN /= latestN)
writeTVar latestNVar newN
case mayA of
Maybe a
Nothing -> STM a
forall a. STM a
STM.retry
Just a
a -> a -> STM a
forall a. a -> STM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a