-- | -- Module : Simulation.Aivika.Trans.Ref.Plain -- Copyright : Copyright (c) 2009-2014, David Sorokin -- License : BSD3 -- Maintainer : David Sorokin -- Stability : experimental -- Tested with: GHC 7.8.3 -- -- This module defines a plain and more fast version of an updatable reference -- that depends on the event queue but that doesn't supply with the signal notification. -- module Simulation.Aivika.Trans.Ref.Plain (Ref, newRef, readRef, writeRef, modifyRef) where import Data.IORef import Control.Monad import Control.Monad.Trans import Simulation.Aivika.Trans.Session import Simulation.Aivika.Trans.ProtoRef import Simulation.Aivika.Trans.Comp import Simulation.Aivika.Trans.Internal.Specs import Simulation.Aivika.Trans.Internal.Simulation import Simulation.Aivika.Trans.Internal.Event -- | The 'Ref' type represents a mutable variable similar to the 'IORef' variable -- but only dependent on the event queue, which allows synchronizing the reference -- with the model explicitly through the 'Event' monad. newtype Ref m a = Ref { refValue :: ProtoRef m a } -- | Create a new reference. newRef :: MonadComp m => a -> Simulation m (Ref m a) newRef a = Simulation $ \r -> do let s = runSession r x <- newProtoRef s a return Ref { refValue = x } -- | Read the value of a reference. readRef :: MonadComp m => Ref m a -> Event m a readRef r = Event $ \p -> readProtoRef (refValue r) -- | Write a new value into the reference. writeRef :: MonadComp m => Ref m a -> a -> Event m () writeRef r a = Event $ \p -> a `seq` writeProtoRef (refValue r) a -- | Mutate the contents of the reference. modifyRef :: MonadComp m => Ref m a -> (a -> a) -> Event m () modifyRef r f = Event $ \p -> do a <- readProtoRef (refValue r) let b = f a b `seq` writeProtoRef (refValue r) b