module Simulation.Aivika.Trans.Ref
(Ref,
refChanged,
refChanged_,
newRef,
newRef0,
readRef,
writeRef,
modifyRef) where
import Data.IORef
import Control.Monad
import Control.Monad.Trans
import Simulation.Aivika.Trans.Internal.Simulation
import Simulation.Aivika.Trans.Internal.Event
import Simulation.Aivika.Trans.Signal
import qualified Simulation.Aivika.Trans.Ref.Base as B
import Simulation.Aivika.Trans.DES
import Simulation.Aivika.Trans.Observable
data Ref m a =
Ref { refValue :: B.Ref m a,
refChangedSource :: SignalSource m a }
newRef :: MonadDES m => a -> Simulation m (Ref m a)
newRef a =
Simulation $ \r ->
do x <- invokeSimulation r $ B.newRef a
s <- invokeSimulation r newSignalSource
return Ref { refValue = x,
refChangedSource = s }
newRef0 :: (MonadDES m, B.MonadRef0 m) => a -> m (Ref m a)
newRef0 a =
do x <- B.newRef0 a
s <- newSignalSource0
return Ref { refValue = x,
refChangedSource = s }
readRef :: MonadDES m => Ref m a -> Event m a
readRef r = B.readRef (refValue r)
writeRef :: MonadDES m => Ref m a -> a -> Event m ()
writeRef r a = Event $ \p ->
do a `seq` invokeEvent p $ B.writeRef (refValue r) a
invokeEvent p $ triggerSignal (refChangedSource r) a
modifyRef :: MonadDES m => Ref m a -> (a -> a) -> Event m ()
modifyRef r f = Event $ \p ->
do a <- invokeEvent p $ B.readRef (refValue r)
let b = f a
b `seq` invokeEvent p $ B.writeRef (refValue r) b
invokeEvent p $ triggerSignal (refChangedSource r) b
refChanged :: Ref m a -> Signal m a
refChanged r = publishSignal (refChangedSource r)
refChanged_ :: MonadDES m => Ref m a -> Signal m ()
refChanged_ r = mapSignal (const ()) $ refChanged r
instance MonadDES m => Eq (Ref m a) where
r1 == r2 = (refValue r1) == (refValue r2)
instance (MonadDES m, Observable (B.Ref m) (t m)) => Observable (Ref m) (t m) where
readObservable r = readObservable (refValue r)