module Dyna.Ref(
  IsRef(..),
) where

import Data.IORef
import Control.Concurrent.STM
import Control.Concurrent.STM.TVar

class IsRef ref where
  newRef    :: a -> IO (ref a)
  readRef   :: ref a -> IO a
  writeRef  :: ref a -> a -> IO ()
  modifyRef :: ref a -> (a -> a) -> IO ()

instance IsRef IORef where
  newRef :: a -> IO (IORef a)
newRef = a -> IO (IORef a)
forall a. a -> IO (IORef a)
newIORef
  readRef :: IORef a -> IO a
readRef = IORef a -> IO a
forall a. IORef a -> IO a
readIORef
  writeRef :: IORef a -> a -> IO ()
writeRef = IORef a -> a -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef
  modifyRef :: IORef a -> (a -> a) -> IO ()
modifyRef = IORef a -> (a -> a) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef'

instance IsRef TVar where
  newRef :: a -> IO (TVar a)
newRef = a -> IO (TVar a)
forall a. a -> IO (TVar a)
newTVarIO
  readRef :: TVar a -> IO a
readRef = TVar a -> IO a
forall a. TVar a -> IO a
readTVarIO
  writeRef :: TVar a -> a -> IO ()
writeRef TVar a
ref a
v = STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ TVar a -> a -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar a
ref a
v
  modifyRef :: TVar a -> (a -> a) -> IO ()
modifyRef TVar a
ref a -> a
f = STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ TVar a -> (a -> a) -> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar a
ref a -> a
f