module Ki.Timeout
  ( timeoutSTM,
  )
where

import Ki.Duration (Duration)
import qualified Ki.Duration as Duration
import Ki.Prelude

-- | Wait for an @STM@ action to return an @IO@ action, or if the given duration elapses, return the given @IO@ action
-- instead.
timeoutSTM :: Duration -> STM (IO a) -> IO a -> IO a
timeoutSTM :: Duration -> STM (IO a) -> IO a -> IO a
timeoutSTM Duration
duration STM (IO a)
action IO a
fallback = do
  (STM ()
delay, IO ()
unregister) <- Int -> IO (STM (), IO ())
registerDelay (Duration -> Int
Duration.toMicroseconds Duration
duration)
  STM (IO a) -> IO a
forall a. STM (IO a) -> IO a
atomicallyIO (STM ()
delay STM () -> IO a -> STM (IO a)
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> IO a
fallback STM (IO a) -> STM (IO a) -> STM (IO a)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (IO ()
unregister IO () -> IO a -> IO a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>) (IO a -> IO a) -> STM (IO a) -> STM (IO a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> STM (IO a)
action)