module CheckedIO.IORef (
  IORef,
  newIORef,
  readIORef,
  writeIORef,
  modifyIORef,
  modifyIORef',
  atomicModifyIORef,
  atomicModifyIORef',
  atomicWriteIORef,
) where

import Data.IORef (IORef)
import qualified Data.IORef as IORef

import CheckedIO.Core (MonadRunIOE, checkIOWith)
import CheckedIO.Prelude

newIORef :: MonadRunIOE e m => a -> m (IORef a)
newIORef :: forall e (m :: * -> *) a. MonadRunIOE e m => a -> m (IORef a)
newIORef a
a = (SomeException -> e) -> UnsafeIO (IORef a) -> m (IORef a)
forall e (m :: * -> *) a.
MonadRunIOE e m =>
(SomeException -> e) -> UnsafeIO a -> m a
checkIOWith SomeException -> e
forall {a} {a}. Show a => a -> a
check (UnsafeIO (IORef a) -> m (IORef a))
-> UnsafeIO (IORef a) -> m (IORef a)
forall a b. (a -> b) -> a -> b
$ a -> UnsafeIO (IORef a)
forall a. a -> IO (IORef a)
IORef.newIORef a
a
  where
    check :: a -> a
check a
e = [Char] -> a
forall a. HasCallStack => [Char] -> a
error ([Char] -> a) -> [Char] -> a
forall a b. (a -> b) -> a -> b
$ [Char]
"newIORef unexpectedly threw an error: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall a. Show a => a -> [Char]
show a
e

readIORef :: MonadRunIOE e m => IORef a -> m a
readIORef :: forall e (m :: * -> *) a. MonadRunIOE e m => IORef a -> m a
readIORef IORef a
ref = (SomeException -> e) -> UnsafeIO a -> m a
forall e (m :: * -> *) a.
MonadRunIOE e m =>
(SomeException -> e) -> UnsafeIO a -> m a
checkIOWith SomeException -> e
forall {a} {a}. Show a => a -> a
check (UnsafeIO a -> m a) -> UnsafeIO a -> m a
forall a b. (a -> b) -> a -> b
$ IORef a -> UnsafeIO a
forall a. IORef a -> IO a
IORef.readIORef IORef a
ref
  where
    check :: a -> a
check a
e = [Char] -> a
forall a. HasCallStack => [Char] -> a
error ([Char] -> a) -> [Char] -> a
forall a b. (a -> b) -> a -> b
$ [Char]
"readIORef unexpectedly threw an error: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall a. Show a => a -> [Char]
show a
e

writeIORef :: MonadRunIOE e m => IORef a -> a -> m ()
writeIORef :: forall e (m :: * -> *) a. MonadRunIOE e m => IORef a -> a -> m ()
writeIORef IORef a
ref a
a = (SomeException -> e) -> UnsafeIO () -> m ()
forall e (m :: * -> *) a.
MonadRunIOE e m =>
(SomeException -> e) -> UnsafeIO a -> m a
checkIOWith SomeException -> e
forall {a} {a}. Show a => a -> a
check (UnsafeIO () -> m ()) -> UnsafeIO () -> m ()
forall a b. (a -> b) -> a -> b
$ IORef a -> a -> UnsafeIO ()
forall a. IORef a -> a -> UnsafeIO ()
IORef.writeIORef IORef a
ref a
a
  where
    check :: a -> a
check a
e = [Char] -> a
forall a. HasCallStack => [Char] -> a
error ([Char] -> a) -> [Char] -> a
forall a b. (a -> b) -> a -> b
$ [Char]
"writeIORef unexpectedly threw an error: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall a. Show a => a -> [Char]
show a
e

modifyIORef :: MonadRunIOE e m => IORef a -> (a -> a) -> m ()
modifyIORef :: forall e (m :: * -> *) a.
MonadRunIOE e m =>
IORef a -> (a -> a) -> m ()
modifyIORef IORef a
ref a -> a
f = (SomeException -> e) -> UnsafeIO () -> m ()
forall e (m :: * -> *) a.
MonadRunIOE e m =>
(SomeException -> e) -> UnsafeIO a -> m a
checkIOWith SomeException -> e
forall {a} {a}. Show a => a -> a
check (UnsafeIO () -> m ()) -> UnsafeIO () -> m ()
forall a b. (a -> b) -> a -> b
$ IORef a -> (a -> a) -> UnsafeIO ()
forall a. IORef a -> (a -> a) -> UnsafeIO ()
IORef.modifyIORef IORef a
ref a -> a
f
  where
    check :: a -> a
check a
e = [Char] -> a
forall a. HasCallStack => [Char] -> a
error ([Char] -> a) -> [Char] -> a
forall a b. (a -> b) -> a -> b
$ [Char]
"modifyIORef unexpectedly threw an error: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall a. Show a => a -> [Char]
show a
e

modifyIORef' :: MonadRunIOE e m => IORef a -> (a -> a) -> m ()
modifyIORef' :: forall e (m :: * -> *) a.
MonadRunIOE e m =>
IORef a -> (a -> a) -> m ()
modifyIORef' IORef a
ref a -> a
f = (SomeException -> e) -> UnsafeIO () -> m ()
forall e (m :: * -> *) a.
MonadRunIOE e m =>
(SomeException -> e) -> UnsafeIO a -> m a
checkIOWith SomeException -> e
forall {a} {a}. Show a => a -> a
check (UnsafeIO () -> m ()) -> UnsafeIO () -> m ()
forall a b. (a -> b) -> a -> b
$ IORef a -> (a -> a) -> UnsafeIO ()
forall a. IORef a -> (a -> a) -> UnsafeIO ()
IORef.modifyIORef' IORef a
ref a -> a
f
  where
    check :: a -> a
check a
e = [Char] -> a
forall a. HasCallStack => [Char] -> a
error ([Char] -> a) -> [Char] -> a
forall a b. (a -> b) -> a -> b
$ [Char]
"modifyIORef' unexpectedly threw an error: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall a. Show a => a -> [Char]
show a
e

atomicModifyIORef :: MonadRunIOE e m => IORef a -> (a -> (a, b)) -> m b
atomicModifyIORef :: forall e (m :: * -> *) a b.
MonadRunIOE e m =>
IORef a -> (a -> (a, b)) -> m b
atomicModifyIORef IORef a
ref a -> (a, b)
f = (SomeException -> e) -> UnsafeIO b -> m b
forall e (m :: * -> *) a.
MonadRunIOE e m =>
(SomeException -> e) -> UnsafeIO a -> m a
checkIOWith SomeException -> e
forall {a} {a}. Show a => a -> a
check (UnsafeIO b -> m b) -> UnsafeIO b -> m b
forall a b. (a -> b) -> a -> b
$ IORef a -> (a -> (a, b)) -> UnsafeIO b
forall a b. IORef a -> (a -> (a, b)) -> IO b
IORef.atomicModifyIORef IORef a
ref a -> (a, b)
f
  where
    check :: a -> a
check a
e = [Char] -> a
forall a. HasCallStack => [Char] -> a
error ([Char] -> a) -> [Char] -> a
forall a b. (a -> b) -> a -> b
$ [Char]
"atomicModifyIORef unexpectedly threw an error: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall a. Show a => a -> [Char]
show a
e

atomicModifyIORef' :: MonadRunIOE e m => IORef a -> (a -> (a, b)) -> m b
atomicModifyIORef' :: forall e (m :: * -> *) a b.
MonadRunIOE e m =>
IORef a -> (a -> (a, b)) -> m b
atomicModifyIORef' IORef a
ref a -> (a, b)
f = (SomeException -> e) -> UnsafeIO b -> m b
forall e (m :: * -> *) a.
MonadRunIOE e m =>
(SomeException -> e) -> UnsafeIO a -> m a
checkIOWith SomeException -> e
forall {a} {a}. Show a => a -> a
check (UnsafeIO b -> m b) -> UnsafeIO b -> m b
forall a b. (a -> b) -> a -> b
$ IORef a -> (a -> (a, b)) -> UnsafeIO b
forall a b. IORef a -> (a -> (a, b)) -> IO b
IORef.atomicModifyIORef' IORef a
ref a -> (a, b)
f
  where
    check :: a -> a
check a
e = [Char] -> a
forall a. HasCallStack => [Char] -> a
error ([Char] -> a) -> [Char] -> a
forall a b. (a -> b) -> a -> b
$ [Char]
"atomicModifyIORef' unexpectedly threw an error: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall a. Show a => a -> [Char]
show a
e

atomicWriteIORef :: MonadRunIOE e m => IORef a -> a -> m ()
atomicWriteIORef :: forall e (m :: * -> *) a. MonadRunIOE e m => IORef a -> a -> m ()
atomicWriteIORef IORef a
ref a
a = (SomeException -> e) -> UnsafeIO () -> m ()
forall e (m :: * -> *) a.
MonadRunIOE e m =>
(SomeException -> e) -> UnsafeIO a -> m a
checkIOWith SomeException -> e
forall {a} {a}. Show a => a -> a
check (UnsafeIO () -> m ()) -> UnsafeIO () -> m ()
forall a b. (a -> b) -> a -> b
$ IORef a -> a -> UnsafeIO ()
forall a. IORef a -> a -> UnsafeIO ()
IORef.atomicWriteIORef IORef a
ref a
a
  where
    check :: a -> a
check a
e = [Char] -> a
forall a. HasCallStack => [Char] -> a
error ([Char] -> a) -> [Char] -> a
forall a b. (a -> b) -> a -> b
$ [Char]
"atomicWriteIORef unexpectedly threw an error: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall a. Show a => a -> [Char]
show a
e

-- TODO: mkWeakIORef