{-# language Safe #-}

module LazyAsync.Actions.Start where

import LazyAsync.Types (Complex (..), LazyAsync (..), StartPoll (..))

import LazyAsync.Prelude (Applicative ((*>)), IO, MonadBase (..), MonadIO (..),
                          STM, atomically, return)

-- | 🚀 Starts an asynchronous action, if it has not already been started
start :: (MonadBase base m, MonadIO base) => LazyAsync a -> m ()
start :: LazyAsync a -> m ()
start Pure{}               = () -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
start Empty{}              = () -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
start (A1 (StartPoll STM ()
s STM (Status a)
_)) = base () -> m ()
forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
liftBase (IO () -> base ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (STM () -> IO ()
forall a. STM a -> IO a
atomically STM ()
s))
start (A2 (Complex Status x -> Status y -> Status a
_ LazyAsync x
x LazyAsync y
y)) = LazyAsync x -> m ()
forall (base :: * -> *) (m :: * -> *) a.
(MonadBase base m, MonadIO base) =>
LazyAsync a -> m ()
start LazyAsync x
x m () -> m () -> m ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> LazyAsync y -> m ()
forall (base :: * -> *) (m :: * -> *) a.
(MonadBase base m, MonadIO base) =>
LazyAsync a -> m ()
start LazyAsync y
y

-- | Akin to 'start'
startIO :: LazyAsync a -> IO ()
startIO :: LazyAsync a -> IO ()
startIO = LazyAsync a -> IO ()
forall (base :: * -> *) (m :: * -> *) a.
(MonadBase base m, MonadIO base) =>
LazyAsync a -> m ()
start

-- | Akin to 'start'
startSTM :: LazyAsync a -> STM ()
startSTM :: LazyAsync a -> STM ()
startSTM Pure{}               = () -> STM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
startSTM Empty{}              = () -> STM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
startSTM (A1 (StartPoll STM ()
s STM (Status a)
_)) = STM ()
s
startSTM (A2 (Complex Status x -> Status y -> Status a
_ LazyAsync x
x LazyAsync y
y)) = LazyAsync x -> STM ()
forall a. LazyAsync a -> STM ()
startSTM LazyAsync x
x STM () -> STM () -> STM ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> LazyAsync y -> STM ()
forall a. LazyAsync a -> STM ()
startSTM LazyAsync y
y