cachix-1.7.9: src/Cachix/Daemon/ShutdownLatch.hs
module Cachix.Daemon.ShutdownLatch
( ShutdownLatch,
newShutdownLatch,
waitForShutdown,
initiateShutdown,
initiateShutdownWithResult,
getResult,
isShuttingDown,
-- STM operations
isShuttingDownSTM,
initiateShutdownSTM,
initiateShutdownWithResultSTM,
getResultSTM,
waitForShutdownSTM,
)
where
import Control.Concurrent.STM
import Protolude
-- | A latch to keep track of the shutdown process.
-- A shutdown latch holds a result value (Either e a) when shutdown is initiated.
-- Nothing means that shutdown has not been requested yet.
newtype ShutdownLatch e a = ShutdownLatch {unShutdownLatch :: TVar (Maybe (Either e a))}
-- | Create a new shutdown latch
newShutdownLatch :: (MonadIO m) => m (ShutdownLatch e a)
newShutdownLatch = ShutdownLatch <$> liftIO (newTVarIO Nothing)
-- | Block until shutdown is requested and return the result
waitForShutdown :: (MonadIO m) => ShutdownLatch e a -> m (Either e a)
waitForShutdown latch = liftIO $ atomically $ waitForShutdownSTM latch
-- | Signal shutdown with a "success" result
initiateShutdown :: (MonadIO m) => a -> ShutdownLatch e a -> m ()
initiateShutdown val latch = liftIO $ atomically $ initiateShutdownSTM val latch
-- | Signal shutdown with a specific result
initiateShutdownWithResult :: (MonadIO m) => Either e a -> ShutdownLatch e a -> m ()
initiateShutdownWithResult result latch = liftIO $ atomically $ initiateShutdownWithResultSTM result latch
-- | Get the shutdown result if available
getResult :: (MonadIO m) => ShutdownLatch e a -> m (Maybe (Either e a))
getResult latch = liftIO $ atomically $ getResultSTM latch
-- | Check if shutdown has been requested
isShuttingDown :: (MonadIO m) => ShutdownLatch e a -> m Bool
isShuttingDown latch = liftIO $ atomically $ isShuttingDownSTM latch
-- STM Operations for use in atomic transactions
-- | Check if shutdown is requested
isShuttingDownSTM :: ShutdownLatch e a -> STM Bool
isShuttingDownSTM latch = isJust <$> readTVar (unShutdownLatch latch)
-- | Signal shutdown with a "success" result
initiateShutdownSTM :: a -> ShutdownLatch e a -> STM ()
initiateShutdownSTM val latch = writeTVar (unShutdownLatch latch) (Just (Right val))
-- | Signal shutdown with a specific result
initiateShutdownWithResultSTM :: Either e a -> ShutdownLatch e a -> STM ()
initiateShutdownWithResultSTM result latch = writeTVar (unShutdownLatch latch) (Just result)
-- | Get the shutdown result (if available)
getResultSTM :: ShutdownLatch e a -> STM (Maybe (Either e a))
getResultSTM = readTVar . unShutdownLatch
-- | Block until shutdown is requested, then return the result
waitForShutdownSTM :: ShutdownLatch e a -> STM (Either e a)
waitForShutdownSTM latch = do
mresult <- readTVar (unShutdownLatch latch)
maybe retry return mresult