packages feed

unfork-1.0.0.0: Unfork/Async/WithResult/IO.hs

{-

I/O, asynchronous, with task results available

Similar to its STM counterpart, but uses MVar instead of TVar.

-}

module Unfork.Async.WithResult.IO
    (
        unforkAsyncIO,
        Future, await, poll,
    )
    where

import Unfork.Async.Core
import Unfork.Async.WithResult.Future
import Unfork.Async.WithResult.Task

import Prelude (IO, pure)

import Control.Monad.STM (atomically)

import qualified Control.Concurrent.MVar as MVar

{- |

    Unforks an action, with the new action's asynchronous result available as @('IO' ('Future' result))@

    Related functions:

      - Use 'Unfork.unforkAsyncIO_' if you do not need to know when the action has completed or obtain its result value
      - Use 'Unfork.unforkAsyncSTM' if you need the composability of 'Control.Monad.STM.STM'

-}

unforkAsyncIO ::
    (task -> IO result) -- ^ Action that needs to be run serially
    -> ((task -> IO (Future result)) -> IO conclusion) -- ^ Continuation with the unforked action
    -> IO conclusion

unforkAsyncIO action =
    unforkAsync Unfork{ unforkedAction, executeOneTask }
  where
    unforkedAction ctx arg = do
        resultVar <- MVar.newEmptyMVar
        atomically (enqueue ctx Task{ arg, resultVar })
        pure (Future resultVar)
    executeOneTask Task{ arg, resultVar } = do
          b <- action arg
          MVar.putMVar resultVar b