-- | Lifted "Control.Concurrent.STM".
module Effectful.Concurrent.STM
  ( -- * Effect
    Concurrent

    -- ** Handlers
  , runConcurrent

    -- * Core
  , STM.STM
  , atomically
  , STM.retry
  , STM.orElse
  , STM.check
  , STM.throwSTM
  , STM.catchSTM

    -- * TVar
  , STM.TVar
  , newTVarIO
  , readTVarIO
  , STM.newTVar
  , STM.readTVar
  , STM.writeTVar
  , STM.modifyTVar
  , STM.modifyTVar'
  , STM.swapTVar
  , registerDelay
  , mkWeakTVar

    -- * TMVar
  , STM.TMVar
  , STM.newTMVar
  , STM.newEmptyTMVar
  , newTMVarIO
  , newEmptyTMVarIO
  , STM.takeTMVar
  , STM.putTMVar
  , STM.readTMVar
  , STM.tryReadTMVar
  , STM.swapTMVar
  , STM.tryTakeTMVar
  , STM.tryPutTMVar
  , STM.isEmptyTMVar
  , mkWeakTMVar

    -- * TChan
  , STM.TChan
  , STM.newTChan
  , newTChanIO
  , STM.newBroadcastTChan
  , newBroadcastTChanIO
  , STM.dupTChan
  , STM.cloneTChan
  , STM.readTChan
  , STM.tryReadTChan
  , STM.peekTChan
  , STM.tryPeekTChan
  , STM.writeTChan
  , STM.unGetTChan
  , STM.isEmptyTChan

    -- * TQueue
  , STM.TQueue
  , STM.newTQueue
  , newTQueueIO
  , STM.readTQueue
  , STM.tryReadTQueue
  , STM.peekTQueue
  , STM.tryPeekTQueue
  , STM.flushTQueue
  , STM.writeTQueue
  , STM.unGetTQueue
  , STM.isEmptyTQueue

    -- * TBQueue
  , STM.TBQueue
  , STM.newTBQueue
  , newTBQueueIO
  , STM.readTBQueue
  , STM.tryReadTBQueue
  , STM.peekTBQueue
  , STM.tryPeekTBQueue
  , STM.flushTBQueue
  , STM.writeTBQueue
  , STM.unGetTBQueue
  , STM.lengthTBQueue
  , STM.isEmptyTBQueue
  , STM.isFullTBQueue
  ) where

import Control.Concurrent.STM (STM, TVar, TMVar, TChan, TQueue, TBQueue)
import Control.Concurrent.STM qualified as STM
import System.Mem.Weak (Weak)
import GHC.Natural (Natural)

import Effectful
import Effectful.Concurrent.Effect
import Effectful.Dispatch.Static
import Effectful.Dispatch.Static.Primitive

-- | Lifted 'STM.atomically'.
atomically :: Concurrent :> es => STM a -> Eff es a
atomically :: forall (es :: [Effect]) a. (Concurrent :> es) => STM a -> Eff es a
atomically = IO a -> Eff es a
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO a -> Eff es a) -> (STM a -> IO a) -> STM a -> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. STM a -> IO a
forall a. STM a -> IO a
STM.atomically

-- | Lifted 'STM.newTVarIO'.
newTVarIO :: Concurrent :> es => a -> Eff es (TVar a)
newTVarIO :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
a -> Eff es (TVar a)
newTVarIO = IO (TVar a) -> Eff es (TVar a)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO (TVar a) -> Eff es (TVar a))
-> (a -> IO (TVar a)) -> a -> Eff es (TVar a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> IO (TVar a)
forall a. a -> IO (TVar a)
STM.newTVarIO

-- | Lifted 'STM.readTVarIO'.
readTVarIO :: Concurrent :> es => TVar a -> Eff es a
readTVarIO :: forall (es :: [Effect]) a. (Concurrent :> es) => TVar a -> Eff es a
readTVarIO = IO a -> Eff es a
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO a -> Eff es a) -> (TVar a -> IO a) -> TVar a -> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TVar a -> IO a
forall a. TVar a -> IO a
STM.readTVarIO

-- | Lifted 'STM.registerDelay'.
registerDelay :: Concurrent :> es => Int -> Eff es (TVar Bool)
registerDelay :: forall (es :: [Effect]).
(Concurrent :> es) =>
Int -> Eff es (TVar Bool)
registerDelay = IO (TVar Bool) -> Eff es (TVar Bool)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO (TVar Bool) -> Eff es (TVar Bool))
-> (Int -> IO (TVar Bool)) -> Int -> Eff es (TVar Bool)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> IO (TVar Bool)
STM.registerDelay

-- | Lifted 'STM.mkWeakTVar'.
mkWeakTVar :: Concurrent :> es => TVar a -> Eff es () -> Eff es (Weak (TVar a))
mkWeakTVar :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
TVar a -> Eff es () -> Eff es (Weak (TVar a))
mkWeakTVar TVar a
var Eff es ()
f = (Env es -> IO (Weak (TVar a))) -> Eff es (Weak (TVar a))
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO (Weak (TVar a))) -> Eff es (Weak (TVar a)))
-> (Env es -> IO (Weak (TVar a))) -> Eff es (Weak (TVar a))
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  -- The finalizer can run at any point and in any thread.
  TVar a -> IO () -> IO (Weak (TVar a))
forall a. TVar a -> IO () -> IO (Weak (TVar a))
STM.mkWeakTVar TVar a
var (IO () -> IO (Weak (TVar a)))
-> (Env es -> IO ()) -> Env es -> IO (Weak (TVar 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 (TVar a))) -> IO (Env es) -> IO (Weak (TVar a))
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es

-- | Lifted 'STM.newTMVarIO'.
newTMVarIO :: Concurrent :> es => a -> Eff es (TMVar a)
newTMVarIO :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
a -> Eff es (TMVar a)
newTMVarIO = IO (TMVar a) -> Eff es (TMVar a)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO (TMVar a) -> Eff es (TMVar a))
-> (a -> IO (TMVar a)) -> a -> Eff es (TMVar a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> IO (TMVar a)
forall a. a -> IO (TMVar a)
STM.newTMVarIO

-- | Lifted 'STM.newEmptyTMVarIO'.
newEmptyTMVarIO :: Concurrent :> es => Eff es (TMVar a)
newEmptyTMVarIO :: forall (es :: [Effect]) a. (Concurrent :> es) => Eff es (TMVar a)
newEmptyTMVarIO = IO (TMVar a) -> Eff es (TMVar a)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ IO (TMVar a)
forall a. IO (TMVar a)
STM.newEmptyTMVarIO

-- | Lifted 'STM.mkWeakTMVar'.
mkWeakTMVar :: Concurrent :> es => TMVar a -> Eff es () -> Eff es (Weak (TMVar a))
mkWeakTMVar :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
TMVar a -> Eff es () -> Eff es (Weak (TMVar a))
mkWeakTMVar TMVar a
var Eff es ()
f = (Env es -> IO (Weak (TMVar a))) -> Eff es (Weak (TMVar a))
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO (Weak (TMVar a))) -> Eff es (Weak (TMVar a)))
-> (Env es -> IO (Weak (TMVar a))) -> Eff es (Weak (TMVar a))
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  -- The finalizer can run at any point and in any thread.
  TMVar a -> IO () -> IO (Weak (TMVar a))
forall a. TMVar a -> IO () -> IO (Weak (TMVar a))
STM.mkWeakTMVar TMVar a
var (IO () -> IO (Weak (TMVar a)))
-> (Env es -> IO ()) -> Env es -> IO (Weak (TMVar 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 (TMVar a)))
-> IO (Env es) -> IO (Weak (TMVar a))
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es

-- | Lifted 'STM.newTChanIO'.
newTChanIO :: Concurrent :> es => Eff es (TChan a)
newTChanIO :: forall (es :: [Effect]) a. (Concurrent :> es) => Eff es (TChan a)
newTChanIO = IO (TChan a) -> Eff es (TChan a)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ IO (TChan a)
forall a. IO (TChan a)
STM.newTChanIO

-- | Lifted 'STM.newBroadcastTChanIO'.
newBroadcastTChanIO :: Concurrent :> es => Eff es (TChan a)
newBroadcastTChanIO :: forall (es :: [Effect]) a. (Concurrent :> es) => Eff es (TChan a)
newBroadcastTChanIO = IO (TChan a) -> Eff es (TChan a)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ IO (TChan a)
forall a. IO (TChan a)
STM.newBroadcastTChanIO

-- | Lifted 'STM.newTQueueIO'.
newTQueueIO :: Concurrent :> es => Eff es (TQueue a)
newTQueueIO :: forall (es :: [Effect]) a. (Concurrent :> es) => Eff es (TQueue a)
newTQueueIO = IO (TQueue a) -> Eff es (TQueue a)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ IO (TQueue a)
forall a. IO (TQueue a)
STM.newTQueueIO

-- | Lifted 'STM.newTBQueueIO'.
newTBQueueIO :: Concurrent :> es => Natural -> Eff es (TBQueue a)
newTBQueueIO :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
Natural -> Eff es (TBQueue a)
newTBQueueIO = IO (TBQueue a) -> Eff es (TBQueue a)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO (TBQueue a) -> Eff es (TBQueue a))
-> (Natural -> IO (TBQueue a)) -> Natural -> Eff es (TBQueue a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Natural -> IO (TBQueue a)
forall a. Natural -> IO (TBQueue a)
STM.newTBQueueIO