{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NamedFieldPuns #-}
module Capnp.Rpc.Promise
  ( Promise,
    Fulfiller,
    
    newPromise,
    newReadyPromise,
    newPromiseWithCallback,
    newCallback,
    
    fulfill,
    breakPromise,
    breakOrFulfill,
    ErrAlreadyResolved (..),
    
    wait,
  )
where
import Capnp.Gen.Capnp.Rpc
import Capnp.Rpc.Errors ()
import Control.Concurrent.STM
import qualified Control.Exception.Safe as HsExn
import Control.Monad.STM.Class
data ErrAlreadyResolved = ErrAlreadyResolved deriving (Int -> ErrAlreadyResolved -> ShowS
[ErrAlreadyResolved] -> ShowS
ErrAlreadyResolved -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ErrAlreadyResolved] -> ShowS
$cshowList :: [ErrAlreadyResolved] -> ShowS
show :: ErrAlreadyResolved -> String
$cshow :: ErrAlreadyResolved -> String
showsPrec :: Int -> ErrAlreadyResolved -> ShowS
$cshowsPrec :: Int -> ErrAlreadyResolved -> ShowS
Show)
instance HsExn.Exception ErrAlreadyResolved
newtype Fulfiller a = Fulfiller
  { forall a. Fulfiller a -> Either (Parsed Exception) a -> STM ()
callback :: Either (Parsed Exception) a -> STM ()
  }
fulfill :: MonadSTM m => Fulfiller a -> a -> m ()
fulfill :: forall (m :: * -> *) a. MonadSTM m => Fulfiller a -> a -> m ()
fulfill Fulfiller a
f a
val = forall (m :: * -> *) a.
MonadSTM m =>
Fulfiller a -> Either (Parsed Exception) a -> m ()
breakOrFulfill Fulfiller a
f (forall a b. b -> Either a b
Right a
val)
breakPromise :: MonadSTM m => Fulfiller a -> Parsed Exception -> m ()
breakPromise :: forall (m :: * -> *) a.
MonadSTM m =>
Fulfiller a -> Parsed Exception -> m ()
breakPromise Fulfiller a
f Parsed Exception
exn = forall (m :: * -> *) a.
MonadSTM m =>
Fulfiller a -> Either (Parsed Exception) a -> m ()
breakOrFulfill Fulfiller a
f (forall a b. a -> Either a b
Left Parsed Exception
exn)
breakOrFulfill :: MonadSTM m => Fulfiller a -> Either (Parsed Exception) a -> m ()
breakOrFulfill :: forall (m :: * -> *) a.
MonadSTM m =>
Fulfiller a -> Either (Parsed Exception) a -> m ()
breakOrFulfill Fulfiller {Either (Parsed Exception) a -> STM ()
callback :: Either (Parsed Exception) a -> STM ()
$sel:callback:Fulfiller :: forall a. Fulfiller a -> Either (Parsed Exception) a -> STM ()
callback} Either (Parsed Exception) a
result = forall (m :: * -> *) a. MonadSTM m => STM a -> m a
liftSTM forall a b. (a -> b) -> a -> b
$ Either (Parsed Exception) a -> STM ()
callback Either (Parsed Exception) a
result
wait :: MonadSTM m => Promise a -> m a
wait :: forall (m :: * -> *) a. MonadSTM m => Promise a -> m a
wait Promise {TVar (Maybe (Either (Parsed Exception) a))
$sel:var:Promise :: forall a. Promise a -> TVar (Maybe (Either (Parsed Exception) a))
var :: TVar (Maybe (Either (Parsed Exception) a))
var} = forall (m :: * -> *) a. MonadSTM m => STM a -> m a
liftSTM forall a b. (a -> b) -> a -> b
$ do
  Maybe (Either (Parsed Exception) a)
val <- forall a. TVar a -> STM a
readTVar TVar (Maybe (Either (Parsed Exception) a))
var
  case Maybe (Either (Parsed Exception) a)
val of
    Maybe (Either (Parsed Exception) a)
Nothing ->
      forall a. STM a
retry
    Just (Right a
result) ->
      forall (f :: * -> *) a. Applicative f => a -> f a
pure a
result
    Just (Left Parsed Exception
exn) ->
      forall e a. Exception e => e -> STM a
throwSTM Parsed Exception
exn
newReadyPromise :: MonadSTM m => a -> m (Promise a)
newReadyPromise :: forall (m :: * -> *) a. MonadSTM m => a -> m (Promise a)
newReadyPromise a
value = forall (m :: * -> *) a. MonadSTM m => STM a -> m a
liftSTM forall a b. (a -> b) -> a -> b
$ forall a. TVar (Maybe (Either (Parsed Exception) a)) -> Promise a
Promise forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. a -> STM (TVar a)
newTVar (forall a. a -> Maybe a
Just (forall a b. b -> Either a b
Right a
value))
newPromise :: MonadSTM m => m (Promise a, Fulfiller a)
newPromise :: forall (m :: * -> *) a. MonadSTM m => m (Promise a, Fulfiller a)
newPromise = forall (m :: * -> *) a. MonadSTM m => STM a -> m a
liftSTM forall a b. (a -> b) -> a -> b
$ do
  TVar (Maybe (Either (Parsed Exception) a))
var <- forall a. a -> STM (TVar a)
newTVar forall a. Maybe a
Nothing
  forall (f :: * -> *) a. Applicative f => a -> f a
pure
    ( Promise {TVar (Maybe (Either (Parsed Exception) a))
var :: TVar (Maybe (Either (Parsed Exception) a))
$sel:var:Promise :: TVar (Maybe (Either (Parsed Exception) a))
var},
      Fulfiller
        { $sel:callback:Fulfiller :: Either (Parsed Exception) a -> STM ()
callback = \Either (Parsed Exception) a
result -> do
            Maybe (Either (Parsed Exception) a)
val <- forall a. TVar a -> STM a
readTVar TVar (Maybe (Either (Parsed Exception) a))
var
            case Maybe (Either (Parsed Exception) a)
val of
              Maybe (Either (Parsed Exception) a)
Nothing ->
                forall a. TVar a -> a -> STM ()
writeTVar TVar (Maybe (Either (Parsed Exception) a))
var (forall a. a -> Maybe a
Just Either (Parsed Exception) a
result)
              Just Either (Parsed Exception) a
_ ->
                forall e a. Exception e => e -> STM a
throwSTM ErrAlreadyResolved
ErrAlreadyResolved
        }
    )
newPromiseWithCallback :: MonadSTM m => (Either (Parsed Exception) a -> STM ()) -> m (Promise a, Fulfiller a)
newPromiseWithCallback :: forall (m :: * -> *) a.
MonadSTM m =>
(Either (Parsed Exception) a -> STM ())
-> m (Promise a, Fulfiller a)
newPromiseWithCallback Either (Parsed Exception) a -> STM ()
callback = forall (m :: * -> *) a. MonadSTM m => STM a -> m a
liftSTM forall a b. (a -> b) -> a -> b
$ do
  (Promise a
promise, Fulfiller {$sel:callback:Fulfiller :: forall a. Fulfiller a -> Either (Parsed Exception) a -> STM ()
callback = Either (Parsed Exception) a -> STM ()
oldCallback}) <- forall (m :: * -> *) a. MonadSTM m => m (Promise a, Fulfiller a)
newPromise
  forall (f :: * -> *) a. Applicative f => a -> f a
pure
    ( Promise a
promise,
      Fulfiller
        { $sel:callback:Fulfiller :: Either (Parsed Exception) a -> STM ()
callback = \Either (Parsed Exception) a
result -> Either (Parsed Exception) a -> STM ()
oldCallback Either (Parsed Exception) a
result forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Either (Parsed Exception) a -> STM ()
callback Either (Parsed Exception) a
result
        }
    )
newCallback :: MonadSTM m => (Either (Parsed Exception) a -> STM ()) -> m (Fulfiller a)
newCallback :: forall (m :: * -> *) a.
MonadSTM m =>
(Either (Parsed Exception) a -> STM ()) -> m (Fulfiller a)
newCallback = forall (m :: * -> *) a. MonadSTM m => STM a -> m a
liftSTM forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a.
MonadSTM m =>
(Either (Parsed Exception) a -> STM ())
-> m (Promise a, Fulfiller a)
newPromiseWithCallback
newtype Promise a = Promise
  { forall a. Promise a -> TVar (Maybe (Either (Parsed Exception) a))
var :: TVar (Maybe (Either (Parsed Exception) a))
  }
  deriving (Promise a -> Promise a -> Bool
forall a. Promise a -> Promise a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Promise a -> Promise a -> Bool
$c/= :: forall a. Promise a -> Promise a -> Bool
== :: Promise a -> Promise a -> Bool
$c== :: forall a. Promise a -> Promise a -> Bool
Eq)