{-# LANGUAGE TypeFamilies #-}

-- |
-- Module     : Simulation.Aivika.IO.Ref.Base.Strict
-- Copyright  : Copyright (c) 2009-2017, David Sorokin <david.sorokin@gmail.com>
-- License    : BSD3
-- Maintainer : David Sorokin <david.sorokin@gmail.com>
-- Stability  : experimental
-- Tested with: GHC 8.0.1
--
-- The 'IO' monad in an instance of strict 'MonadRef'.
--
module Simulation.Aivika.IO.Ref.Base.Strict () where

import Data.IORef

import Control.Monad
import Control.Monad.Trans

import Simulation.Aivika.Trans.Internal.Types
import Simulation.Aivika.Trans.Ref.Base.Strict

-- | 'IO' is an instance of 'MonadRef'.
instance MonadRef IO where
-- instance (Monad m, MonadIO m, MonadTemplate m) => MonadRef m where

  {-# SPECIALISE instance MonadRef IO #-}

  -- | A type safe wrapper for the 'IORef' reference.
  newtype Ref IO a = Ref { forall a. Ref IO a -> IORef a
refValue :: IORef a }

  {-# INLINE newRef #-}
  newRef :: forall a. a -> Simulation IO (Ref IO a)
newRef a
a =
    forall (m :: * -> *) a. (Run m -> m a) -> Simulation m a
Simulation forall a b. (a -> b) -> a -> b
$ \Run IO
r ->
    do IORef a
x <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall a. a -> IO (IORef a)
newIORef a
a
       forall (m :: * -> *) a. Monad m => a -> m a
return Ref { refValue :: IORef a
refValue = IORef a
x }
     
  {-# INLINE readRef #-}
  readRef :: forall a. Ref IO a -> Event IO a
readRef Ref IO a
r = forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point IO
p ->
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall a. IORef a -> IO a
readIORef (forall a. Ref IO a -> IORef a
refValue Ref IO a
r)

  {-# INLINE writeRef #-}
  writeRef :: forall a. Ref IO a -> a -> Event IO ()
writeRef Ref IO a
r a
a = forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point IO
p -> 
    a
a seq :: forall a b. a -> b -> b
`seq` forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall a. IORef a -> a -> IO ()
writeIORef (forall a. Ref IO a -> IORef a
refValue Ref IO a
r) a
a

  {-# INLINE modifyRef #-}
  modifyRef :: forall a. Ref IO a -> (a -> a) -> Event IO ()
modifyRef Ref IO a
r a -> a
f = forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point IO
p -> 
    do a
a <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall a. IORef a -> IO a
readIORef (forall a. Ref IO a -> IORef a
refValue Ref IO a
r)
       let b :: a
b = a -> a
f a
a
       a
b seq :: forall a b. a -> b -> b
`seq` forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall a. IORef a -> a -> IO ()
writeIORef (forall a. Ref IO a -> IORef a
refValue Ref IO a
r) a
b

  {-# INLINE equalRef #-}
  equalRef :: forall a. Ref IO a -> Ref IO a -> Bool
equalRef (Ref IORef a
r1) (Ref IORef a
r2) = (IORef a
r1 forall a. Eq a => a -> a -> Bool
== IORef a
r2)

-- | 'IO' is an instance of 'MonadRef0'.
instance MonadRef0 IO where
-- instance (MonadIO m, MonadTemplate m) => MonadRef0 m where

  {-# SPECIALISE instance MonadRef0 IO #-}
  
  {-# INLINE newRef0 #-}
  newRef0 :: forall a. a -> IO (Ref IO a)
newRef0 a
a =
    do IORef a
x <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall a. a -> IO (IORef a)
newIORef a
a
       forall (m :: * -> *) a. Monad m => a -> m a
return Ref { refValue :: IORef a
refValue = IORef a
x }