unfork-1.0.0.0: Unfork/Async/WithResult/STM.hs
{-
STM, asynchronous, with task results available
To make task results available, we maintain a queue that contains not only each the task itself, but also a TVar to store its result. Each step of the queue loop runs the action and then places the result into the TVar.
-}
module Unfork.Async.WithResult.STM
(
unforkAsyncSTM,
)
where
import Unfork.Async.Core
import Unfork.Async.WithResult.Task
import Prelude (IO, Maybe (..), pure)
import Control.Monad.STM (STM, atomically)
import qualified Control.Concurrent.STM as STM
{- |
Unforks an action, with the new action's asynchronous result available as @('STM' ('Maybe' result))@
Related functions:
- Use 'Unfork.unforkAsyncSTM_' if you do not need to know when the action has completed or obtain its result value
- Use 'Unfork.unforkAsyncIO' if you do not need the composability of 'STM'
-}
unforkAsyncSTM ::
(task -> IO result) -- ^ Action that needs to be run serially
-> ((task -> STM (STM (Maybe result))) -> IO conclusion) -- ^ Continuation with the unforked action
-> IO conclusion
unforkAsyncSTM action =
unforkAsync Unfork{ unforkedAction, executeOneTask }
where
unforkedAction ctx arg = do
resultVar <- STM.newTVar Nothing
enqueue ctx Task{ arg, resultVar }
pure (STM.readTVar resultVar)
executeOneTask Task{ arg, resultVar } = do
b <- action arg
atomically (STM.writeTVar resultVar (Just b))