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)
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 (TVar (Maybe a, Int) -> Signal a
forall a. TVar (Maybe a, Int) -> Signal a
Signal TVar (Maybe a, Int)
tvar)
writeSignal :: Signal a -> a -> STM ()
writeSignal :: forall a. Signal a -> a -> STM ()
writeSignal (Signal TVar (Maybe a, Int)
signalVar) a
a = do
(Maybe a
_, Int
n) <- TVar (Maybe a, Int) -> STM (Maybe a, Int)
forall a. TVar a -> STM a
readTVar TVar (Maybe a, Int)
signalVar
TVar (Maybe a, Int) -> (Maybe a, Int) -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar (Maybe a, Int)
signalVar (a -> Maybe a
forall a. a -> Maybe a
Just a
a, Int -> Int
forall a. Enum a => a -> a
succ Int
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
(Maybe a
_, Int
n) <- TVar (Maybe a, Int) -> m (Maybe a, Int)
forall (m :: * -> *) a. MonadIO m => TVar a -> m a
readTVarIO TVar (Maybe a, Int)
signalVar
TVar Int
latestNVar <- Int -> m (TVar Int)
forall (m :: * -> *) a. MonadIO m => a -> m (TVar a)
newTVarIO (Int -> Int
forall a. Enum a => a -> a
pred Int
n)
pure $ do
(Maybe a
mayA, Int
newN) <- TVar (Maybe a, Int) -> STM (Maybe a, Int)
forall a. TVar a -> STM a
readTVar TVar (Maybe a, Int)
signalVar
Int
latestN <- TVar Int -> STM Int
forall a. TVar a -> STM a
readTVar TVar Int
latestNVar
Bool -> STM ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Int
newN Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
latestN)
TVar Int -> Int -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar Int
latestNVar Int
newN
case Maybe a
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