module Simulation.Aivika.Trans.Task
(
Task,
TaskResult(..),
taskId,
tryGetTaskResult,
taskResult,
taskResultReceived,
taskProcess,
cancelTask,
taskCancelled,
runTask,
runTaskUsingId,
spawnTask,
spawnTaskUsingId,
enqueueTask,
enqueueTaskUsingId) where
import Data.Monoid
import Control.Monad
import Control.Monad.Trans
import Control.Exception
import Simulation.Aivika.Trans.Specs
import Simulation.Aivika.Trans.ProtoRef
import Simulation.Aivika.Trans.Comp
import Simulation.Aivika.Trans.Internal.Specs
import Simulation.Aivika.Trans.Internal.Parameter
import Simulation.Aivika.Trans.Internal.Simulation
import Simulation.Aivika.Trans.Internal.Dynamics
import Simulation.Aivika.Trans.Internal.Event
import Simulation.Aivika.Trans.Internal.Cont
import Simulation.Aivika.Trans.Internal.Process
import Simulation.Aivika.Trans.Internal.Signal
data Task m a =
Task { taskId :: ProcessId m,
taskResultRef :: ProtoRef m (Maybe (TaskResult a)),
taskResultReceived :: Signal m (TaskResult a)
}
data TaskResult a = TaskCompleted a
| TaskError SomeException
| TaskCancelled
tryGetTaskResult :: MonadComp m => Task m a -> Event m (Maybe (TaskResult a))
tryGetTaskResult t =
Event $ \p -> readProtoRef (taskResultRef t)
taskResult :: MonadComp m => Task m a -> Process m (TaskResult a)
taskResult t =
do x <- liftComp $ readProtoRef (taskResultRef t)
case x of
Just x -> return x
Nothing -> processAwait (taskResultReceived t)
cancelTask :: MonadComp m => Task m a -> Event m ()
cancelTask t =
cancelProcessWithId (taskId t)
taskCancelled :: MonadComp m => Task m a -> Event m Bool
taskCancelled t =
processCancelled (taskId t)
newTaskUsingId :: MonadComp m => ProcessId m -> Process m a -> Event m (Task m a, Process m ())
newTaskUsingId pid p =
do sn <- liftParameter simulationSession
r <- liftComp $ newProtoRef sn Nothing
s <- liftSimulation newSignalSource
let t = Task { taskId = pid,
taskResultRef = r,
taskResultReceived = publishSignal s }
let m =
do v <- liftComp $ newProtoRef sn TaskCancelled
finallyProcess
(catchProcess
(do a <- p
liftComp $ writeProtoRef v (TaskCompleted a))
(\e ->
liftComp $ writeProtoRef v (TaskError e)))
(liftEvent $
do x <- liftComp $ readProtoRef v
liftComp $ writeProtoRef r (Just x)
triggerSignal s x)
return (t, m)
runTaskUsingId :: MonadComp m => ProcessId m -> Process m a -> Event m (Task m a)
runTaskUsingId pid p =
do (t, m) <- newTaskUsingId pid p
runProcessUsingId pid m
return t
runTask :: MonadComp m => Process m a -> Event m (Task m a)
runTask p =
do pid <- liftSimulation newProcessId
runTaskUsingId pid p
enqueueTaskUsingId :: MonadComp m => Double -> ProcessId m -> Process m a -> Event m (Task m a)
enqueueTaskUsingId time pid p =
do (t, m) <- newTaskUsingId pid p
enqueueProcessUsingId time pid m
return t
enqueueTask :: MonadComp m => Double -> Process m a -> Event m (Task m a)
enqueueTask time p =
do pid <- liftSimulation newProcessId
enqueueTaskUsingId time pid p
spawnTaskUsingId :: MonadComp m => ContCancellation -> ProcessId m -> Process m a -> Process m (Task m a)
spawnTaskUsingId cancellation pid p =
do (t, m) <- liftEvent $ newTaskUsingId pid p
spawnProcessUsingId cancellation pid m
return t
spawnTask :: MonadComp m => ContCancellation -> Process m a -> Process m (Task m a)
spawnTask cancellation p =
do pid <- liftSimulation newProcessId
spawnTaskUsingId cancellation pid p
taskProcess :: MonadComp m => Task m a -> Process m a
taskProcess t =
do x <- taskResult t
case x of
TaskCompleted a -> return a
TaskError e -> throwProcess e
TaskCancelled -> cancelProcess