-- |
-- Module     : Simulation.Aivika.Distributed.Optimistic.Internal.Expect
-- Copyright  : Copyright (c) 2015-2017, David Sorokin <david.sorokin@gmail.com>
-- License    : BSD3
-- Maintainer : David Sorokin <david.sorokin@gmail.com>
-- Stability  : experimental
-- Tested with: GHC 7.10.3
--
-- Implements the 'expectProcess' function that allows waiting for some computation to have a determined result.
--
module Simulation.Aivika.Distributed.Optimistic.Internal.Expect
       (expectProcess) where

import Control.Monad
import Control.Monad.Trans

import Simulation.Aivika.Trans
import Simulation.Aivika.Trans.Internal.Types
import Simulation.Aivika.Trans.Internal.Simulation
import Simulation.Aivika.Trans.Internal.Event
import Simulation.Aivika.Trans.Internal.Cont
import Simulation.Aivika.Trans.Internal.Process

import Simulation.Aivika.Distributed.Optimistic.DIO
import Simulation.Aivika.Distributed.Optimistic.Internal.Event

-- | Suspend the 'Process' until the specified computation is determined.
--  
-- The tested computation should depend on messages that come from other logical processes.
-- Moreover, the process must be initiated through the event queue.
--
-- In the current implementation there is a limitation that this function can be used only
-- once for the entire logical process simulation; otherwise, a race condition may arise.
expectProcess :: Event DIO (Maybe a) -> Process DIO a
expectProcess :: forall a. Event DIO (Maybe a) -> Process DIO a
expectProcess Event DIO (Maybe a)
m =
  (ProcessId DIO -> Cont DIO a) -> Process DIO a
forall (m :: * -> *) a. (ProcessId m -> Cont m a) -> Process m a
Process ((ProcessId DIO -> Cont DIO a) -> Process DIO a)
-> (ProcessId DIO -> Cont DIO a) -> Process DIO a
forall a b. (a -> b) -> a -> b
$ \ProcessId DIO
pid ->
  (ContParams DIO a -> Event DIO ()) -> Cont DIO a
forall (m :: * -> *) a. (ContParams m a -> Event m ()) -> Cont m a
Cont ((ContParams DIO a -> Event DIO ()) -> Cont DIO a)
-> (ContParams DIO a -> Event DIO ()) -> Cont DIO a
forall a b. (a -> b) -> a -> b
$ \ContParams DIO a
c ->
  (Point DIO -> DIO ()) -> Event DIO ()
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point DIO -> DIO ()) -> Event DIO ())
-> (Point DIO -> DIO ()) -> Event DIO ()
forall a b. (a -> b) -> a -> b
$ \Point DIO
p ->
  do let t :: Double
t = Point DIO -> Double
forall (m :: * -> *). Point m -> Double
pointTime Point DIO
p
     Point DIO -> Event DIO () -> DIO ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point DIO
p (Event DIO () -> DIO ()) -> Event DIO () -> DIO ()
forall a b. (a -> b) -> a -> b
$
       Event DIO (Maybe a) -> (a -> Event DIO ()) -> Event DIO ()
forall a.
Event DIO (Maybe a) -> (a -> Event DIO ()) -> Event DIO ()
expectEvent Event DIO (Maybe a)
m ((a -> Event DIO ()) -> Event DIO ())
-> (a -> Event DIO ()) -> Event DIO ()
forall a b. (a -> b) -> a -> b
$
       ContParams DIO a -> a -> Event DIO ()
forall (m :: * -> *) a.
MonadDES m =>
ContParams m a -> a -> Event m ()
resumeCont ContParams DIO a
c