module Simulation.Aivika.Ref
(Ref,
refChanged,
refChanged_,
newRef,
readRef,
writeRef,
modifyRef) where
import Data.IORef
import Control.Monad
import Control.Monad.Trans
import Simulation.Aivika.Internal.Simulation
import Simulation.Aivika.Internal.Event
import Simulation.Aivika.Signal
data Ref a =
Ref { refValue :: IORef a,
refChangedSource :: SignalSource a }
newRef :: a -> Simulation (Ref a)
newRef a =
do x <- liftIO $ newIORef a
s <- newSignalSource
return Ref { refValue = x,
refChangedSource = s }
readRef :: Ref a -> Event a
readRef r = Event $ \p -> readIORef (refValue r)
writeRef :: Ref a -> a -> Event ()
writeRef r a = Event $ \p ->
do a `seq` writeIORef (refValue r) a
invokeEvent p $ triggerSignal (refChangedSource r) a
modifyRef :: Ref a -> (a -> a) -> Event ()
modifyRef r f = Event $ \p ->
do a <- readIORef (refValue r)
let b = f a
b `seq` writeIORef (refValue r) b
invokeEvent p $ triggerSignal (refChangedSource r) b
refChanged :: Ref a -> Signal a
refChanged v = publishSignal (refChangedSource v)
refChanged_ :: Ref a -> Signal ()
refChanged_ r = mapSignal (const ()) $ refChanged r