-- | Lifted "Data.IORef.Strict".
--
-- @since 2.4.0.0
module Effectful.Prim.IORef.Strict
  ( -- * Effect
    Prim

    -- ** Handlers
  , runPrim

    -- * IORef
  , IORef'
  , newIORef'
  , readIORef'
  , writeIORef'
  , modifyIORef'
  , atomicModifyIORef'
  , atomicWriteIORef'
  , mkWeakIORef'
  ) where

import Data.IORef.Strict (IORef')
import Data.IORef.Strict qualified as Ref
import System.Mem.Weak (Weak)

import Effectful
import Effectful.Dispatch.Static
import Effectful.Dispatch.Static.Primitive
import Effectful.Prim

-- | Lifted 'Ref.newIORef''.
newIORef' :: Prim :> es => a -> Eff es (IORef' a)
newIORef' :: forall (es :: [Effect]) a. (Prim :> es) => a -> Eff es (IORef' a)
newIORef' = IO (IORef' a) -> Eff es (IORef' a)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO (IORef' a) -> Eff es (IORef' a))
-> (a -> IO (IORef' a)) -> a -> Eff es (IORef' a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> IO (IORef' a)
forall a. a -> IO (IORef' a)
Ref.newIORef'

-- | Lifted 'Ref.readIORef''.
readIORef' :: Prim :> es => IORef' a -> Eff es a
readIORef' :: forall (es :: [Effect]) a. (Prim :> es) => IORef' a -> Eff es a
readIORef' = IO a -> Eff es a
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO a -> Eff es a) -> (IORef' a -> IO a) -> IORef' a -> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IORef' a -> IO a
forall a. IORef' a -> IO a
Ref.readIORef'

-- | Lifted 'Ref.writeIORef''.
writeIORef' :: Prim :> es => IORef' a -> a -> Eff es ()
writeIORef' :: forall (es :: [Effect]) a.
(Prim :> es) =>
IORef' a -> a -> Eff es ()
writeIORef' IORef' a
var = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> (a -> IO ()) -> a -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IORef' a -> a -> IO ()
forall a. IORef' a -> a -> IO ()
Ref.writeIORef' IORef' a
var

-- | Lifted 'Ref.modifyIORef''.
modifyIORef' :: Prim :> es => IORef' a -> (a -> a) -> Eff es ()
modifyIORef' :: forall (es :: [Effect]) a.
(Prim :> es) =>
IORef' a -> (a -> a) -> Eff es ()
modifyIORef' IORef' a
var = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ())
-> ((a -> a) -> IO ()) -> (a -> a) -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IORef' a -> (a -> a) -> IO ()
forall a. IORef' a -> (a -> a) -> IO ()
Ref.modifyIORef' IORef' a
var

-- | Lifted 'Ref.atomicModifyIORef''.
atomicModifyIORef' :: Prim :> es => IORef' a -> (a -> (a, b)) -> Eff es b
atomicModifyIORef' :: forall (es :: [Effect]) a b.
(Prim :> es) =>
IORef' a -> (a -> (a, b)) -> Eff es b
atomicModifyIORef' IORef' a
var = IO b -> Eff es b
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO b -> Eff es b)
-> ((a -> (a, b)) -> IO b) -> (a -> (a, b)) -> Eff es b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IORef' a -> (a -> (a, b)) -> IO b
forall a b. IORef' a -> (a -> (a, b)) -> IO b
Ref.atomicModifyIORef' IORef' a
var

-- | Lifted 'Ref.atomicWriteIORef''.
atomicWriteIORef' :: Prim :> es => IORef' a -> a -> Eff es ()
atomicWriteIORef' :: forall (es :: [Effect]) a.
(Prim :> es) =>
IORef' a -> a -> Eff es ()
atomicWriteIORef' IORef' a
var = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> (a -> IO ()) -> a -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IORef' a -> a -> IO ()
forall a. IORef' a -> a -> IO ()
Ref.atomicWriteIORef' IORef' a
var

-- | Lifted 'Ref.mkWeakIORef''.
--
-- /Note:/ the finalizer will run a cloned environment, so any changes it makes
-- to thread local data will not be visible outside of it.
mkWeakIORef'
  :: (HasCallStack, Prim :> es)
  => IORef' a
  -> Eff es ()
  -> Eff es (Weak (IORef' a))
mkWeakIORef' :: forall (es :: [Effect]) a.
(HasCallStack, Prim :> es) =>
IORef' a -> Eff es () -> Eff es (Weak (IORef' a))
mkWeakIORef' IORef' a
var Eff es ()
f = (Env es -> IO (Weak (IORef' a))) -> Eff es (Weak (IORef' a))
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO (Weak (IORef' a))) -> Eff es (Weak (IORef' a)))
-> (Env es -> IO (Weak (IORef' a))) -> Eff es (Weak (IORef' a))
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  -- The finalizer can run at any point and in any thread.
  IORef' a -> IO () -> IO (Weak (IORef' a))
forall a. IORef' a -> IO () -> IO (Weak (IORef' a))
Ref.mkWeakIORef' IORef' a
var (IO () -> IO (Weak (IORef' a)))
-> (Env es -> IO ()) -> Env es -> IO (Weak (IORef' a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Eff es () -> Env es -> IO ()
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es ()
f (Env es -> IO (Weak (IORef' a)))
-> IO (Env es) -> IO (Weak (IORef' a))
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). HasCallStack => Env es -> IO (Env es)
cloneEnv Env es
es