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 { Ref a -> IORef a
refValue :: IORef a,
Ref a -> SignalSource a
refChangedSource :: SignalSource a }
newRef :: a -> Simulation (Ref a)
newRef :: a -> Simulation (Ref a)
newRef a
a =
do IORef a
x <- IO (IORef a) -> Simulation (IORef a)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (IORef a) -> Simulation (IORef a))
-> IO (IORef a) -> Simulation (IORef a)
forall a b. (a -> b) -> a -> b
$ a -> IO (IORef a)
forall a. a -> IO (IORef a)
newIORef a
a
SignalSource a
s <- Simulation (SignalSource a)
forall a. Simulation (SignalSource a)
newSignalSource
Ref a -> Simulation (Ref a)
forall (m :: * -> *) a. Monad m => a -> m a
return Ref :: forall a. IORef a -> SignalSource a -> Ref a
Ref { refValue :: IORef a
refValue = IORef a
x,
refChangedSource :: SignalSource a
refChangedSource = SignalSource a
s }
readRef :: Ref a -> Event a
readRef :: Ref a -> Event a
readRef Ref a
r = (Point -> IO a) -> Event a
forall a. (Point -> IO a) -> Event a
Event ((Point -> IO a) -> Event a) -> (Point -> IO a) -> Event a
forall a b. (a -> b) -> a -> b
$ \Point
p -> IORef a -> IO a
forall a. IORef a -> IO a
readIORef (Ref a -> IORef a
forall a. Ref a -> IORef a
refValue Ref a
r)
writeRef :: Ref a -> a -> Event ()
writeRef :: Ref a -> a -> Event ()
writeRef Ref a
r a
a = (Point -> IO ()) -> Event ()
forall a. (Point -> IO a) -> Event a
Event ((Point -> IO ()) -> Event ()) -> (Point -> IO ()) -> Event ()
forall a b. (a -> b) -> a -> b
$ \Point
p ->
do a
a a -> IO () -> IO ()
`seq` IORef a -> a -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef (Ref a -> IORef a
forall a. Ref a -> IORef a
refValue Ref a
r) a
a
Point -> Event () -> IO ()
forall a. Point -> Event a -> IO a
invokeEvent Point
p (Event () -> IO ()) -> Event () -> IO ()
forall a b. (a -> b) -> a -> b
$ SignalSource a -> a -> Event ()
forall a. SignalSource a -> a -> Event ()
triggerSignal (Ref a -> SignalSource a
forall a. Ref a -> SignalSource a
refChangedSource Ref a
r) a
a
modifyRef :: Ref a -> (a -> a) -> Event ()
modifyRef :: Ref a -> (a -> a) -> Event ()
modifyRef Ref a
r a -> a
f = (Point -> IO ()) -> Event ()
forall a. (Point -> IO a) -> Event a
Event ((Point -> IO ()) -> Event ()) -> (Point -> IO ()) -> Event ()
forall a b. (a -> b) -> a -> b
$ \Point
p ->
do a
a <- IORef a -> IO a
forall a. IORef a -> IO a
readIORef (Ref a -> IORef a
forall a. Ref a -> IORef a
refValue Ref a
r)
let b :: a
b = a -> a
f a
a
a
b a -> IO () -> IO ()
`seq` IORef a -> a -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef (Ref a -> IORef a
forall a. Ref a -> IORef a
refValue Ref a
r) a
b
Point -> Event () -> IO ()
forall a. Point -> Event a -> IO a
invokeEvent Point
p (Event () -> IO ()) -> Event () -> IO ()
forall a b. (a -> b) -> a -> b
$ SignalSource a -> a -> Event ()
forall a. SignalSource a -> a -> Event ()
triggerSignal (Ref a -> SignalSource a
forall a. Ref a -> SignalSource a
refChangedSource Ref a
r) a
b
refChanged :: Ref a -> Signal a
refChanged :: Ref a -> Signal a
refChanged Ref a
v = SignalSource a -> Signal a
forall a. SignalSource a -> Signal a
publishSignal (Ref a -> SignalSource a
forall a. Ref a -> SignalSource a
refChangedSource Ref a
v)
refChanged_ :: Ref a -> Signal ()
refChanged_ :: Ref a -> Signal ()
refChanged_ Ref a
r = (a -> ()) -> Signal a -> Signal ()
forall a b. (a -> b) -> Signal a -> Signal b
mapSignal (() -> a -> ()
forall a b. a -> b -> a
const ()) (Signal a -> Signal ()) -> Signal a -> Signal ()
forall a b. (a -> b) -> a -> b
$ Ref a -> Signal a
forall a. Ref a -> Signal a
refChanged Ref a
r