-- | Lifted "Control.Concurrent.MVar" with operations that force values put
-- inside an 'MVar' to WHNF.
module Effectful.Concurrent.MVar.Strict
  ( -- * Effect
    Concurrent

    -- ** Handlers
  , runConcurrent

    -- * MVar
  , MVar
  , newEmptyMVar
  , newMVar
  , takeMVar
  , putMVar
  , readMVar
  , swapMVar
  , tryTakeMVar
  , tryPutMVar
  , isEmptyMVar
  , withMVar
  , withMVarMasked
  , modifyMVar
  , modifyMVar_
  , modifyMVarMasked
  , modifyMVarMasked_
  , tryReadMVar
  , mkWeakMVar
  ) where

import System.Mem.Weak (Weak)
import Control.Concurrent.MVar (MVar)
import qualified Control.Concurrent.MVar as M

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

-- | Lifted 'M.newEmptyMVar'.
newEmptyMVar :: Concurrent :> es => Eff es (MVar a)
newEmptyMVar :: forall (es :: [Effect]) a. (Concurrent :> es) => Eff es (MVar a)
newEmptyMVar = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall a. IO (MVar a)
M.newEmptyMVar

-- | Lifted 'M.newMVar' that evaluates the value to WHNF.
newMVar :: Concurrent :> es => a -> Eff es (MVar a)
newMVar :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
a -> Eff es (MVar a)
newMVar a
a = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall a b. (a -> b) -> a -> b
$ a
a seq :: forall a b. a -> b -> b
`seq` forall a. a -> IO (MVar a)
M.newMVar a
a

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

-- | Lifted 'M.putMVar'.
putMVar :: Concurrent :> es => MVar a -> a -> Eff es ()
putMVar :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
MVar a -> a -> Eff es ()
putMVar MVar a
var a
a = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall a b. (a -> b) -> a -> b
$ a
a seq :: forall a b. a -> b -> b
`seq` forall a. MVar a -> a -> IO ()
M.putMVar MVar a
var a
a

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

-- | Lifted 'M.swapMVar' that evaluates the new value to WHNF.
swapMVar :: Concurrent :> es => MVar a -> a -> Eff es a
swapMVar :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
MVar a -> a -> Eff es a
swapMVar MVar a
var a
a = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall a b. (a -> b) -> a -> b
$ a
a seq :: forall a b. a -> b -> b
`seq` forall a. MVar a -> a -> IO a
M.swapMVar MVar a
var a
a

-- | Lifted 'M.tryTakeMVar'.
tryTakeMVar :: Concurrent :> es => MVar a -> Eff es (Maybe a)
tryTakeMVar :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
MVar a -> Eff es (Maybe a)
tryTakeMVar = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. MVar a -> IO (Maybe a)
M.tryTakeMVar

-- | Lifted 'M.tryPutMVar' that evaluates the new value to WHNF.
tryPutMVar :: Concurrent :> es => MVar a -> a -> Eff es Bool
tryPutMVar :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
MVar a -> a -> Eff es Bool
tryPutMVar MVar a
var a
a = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall a b. (a -> b) -> a -> b
$ a
a seq :: forall a b. a -> b -> b
`seq` forall a. MVar a -> a -> IO Bool
M.tryPutMVar MVar a
var a
a

-- | Lifted 'M.isEmptyMVar'.
isEmptyMVar :: Concurrent :> es => MVar a -> Eff es Bool
isEmptyMVar :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
MVar a -> Eff es Bool
isEmptyMVar = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. MVar a -> IO Bool
M.isEmptyMVar

-- | Lifted 'M.tryReadMVar'.
tryReadMVar :: Concurrent :> es => MVar a -> Eff es (Maybe a)
tryReadMVar :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
MVar a -> Eff es (Maybe a)
tryReadMVar = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. MVar a -> IO (Maybe a)
M.tryReadMVar

-- | Lifted 'M.withMVar'.
withMVar :: Concurrent :> es => MVar a -> (a -> Eff es b) -> Eff es b
withMVar :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
MVar a -> (a -> Eff es b) -> Eff es b
withMVar MVar a
var a -> Eff es b
f = forall (es :: [Effect]) a.
((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
reallyUnsafeUnliftIO forall a b. (a -> b) -> a -> b
$ \forall r. Eff es r -> IO r
unlift -> do
  forall a b. MVar a -> (a -> IO b) -> IO b
M.withMVar MVar a
var forall a b. (a -> b) -> a -> b
$ forall r. Eff es r -> IO r
unlift forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Eff es b
f

-- | Lifted 'M.withMVarMasked'.
withMVarMasked :: Concurrent :> es => MVar a -> (a -> Eff es b) -> Eff es b
withMVarMasked :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
MVar a -> (a -> Eff es b) -> Eff es b
withMVarMasked MVar a
var a -> Eff es b
f = forall (es :: [Effect]) a.
((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
reallyUnsafeUnliftIO forall a b. (a -> b) -> a -> b
$ \forall r. Eff es r -> IO r
unlift -> do
  forall a b. MVar a -> (a -> IO b) -> IO b
M.withMVarMasked MVar a
var forall a b. (a -> b) -> a -> b
$ forall r. Eff es r -> IO r
unlift forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Eff es b
f

-- | Lifted 'M.modifyMVar_' that evaluates the new value to WHNF.
modifyMVar_ :: Concurrent :> es => MVar a -> (a -> Eff es a) -> Eff es ()
modifyMVar_ :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
MVar a -> (a -> Eff es a) -> Eff es ()
modifyMVar_ MVar a
var a -> Eff es a
f = forall (es :: [Effect]) a.
((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
reallyUnsafeUnliftIO forall a b. (a -> b) -> a -> b
$ \forall r. Eff es r -> IO r
unlift -> do
  forall a. MVar a -> (a -> IO a) -> IO ()
M.modifyMVar_ MVar a
var forall a b. (a -> b) -> a -> b
$ \a
a0 -> do
    a
a <- forall r. Eff es r -> IO r
unlift forall a b. (a -> b) -> a -> b
$ a -> Eff es a
f a
a0
    a
a seq :: forall a b. a -> b -> b
`seq` forall (f :: Type -> Type) a. Applicative f => a -> f a
pure a
a

-- | Lifted 'M.modifyMVar' that evaluates the new value to WHNF.
modifyMVar :: Concurrent :> es => MVar a -> (a -> Eff es (a, b)) -> Eff es b
modifyMVar :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
MVar a -> (a -> Eff es (a, b)) -> Eff es b
modifyMVar MVar a
var a -> Eff es (a, b)
f = forall (es :: [Effect]) a.
((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
reallyUnsafeUnliftIO forall a b. (a -> b) -> a -> b
$ \forall r. Eff es r -> IO r
unlift -> do
  forall a b. MVar a -> (a -> IO (a, b)) -> IO b
M.modifyMVar MVar a
var forall a b. (a -> b) -> a -> b
$ \a
a0 -> do
    (a
a, b
b) <- forall r. Eff es r -> IO r
unlift forall a b. (a -> b) -> a -> b
$ a -> Eff es (a, b)
f a
a0
    a
a seq :: forall a b. a -> b -> b
`seq` forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (a
a, b
b)

-- | Lifted 'M.modifyMVarMasked_' that evaluates the new value to WHNF.
modifyMVarMasked_ :: Concurrent :> es => MVar a -> (a -> Eff es a) -> Eff es ()
modifyMVarMasked_ :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
MVar a -> (a -> Eff es a) -> Eff es ()
modifyMVarMasked_ MVar a
var a -> Eff es a
f = forall (es :: [Effect]) a.
((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
reallyUnsafeUnliftIO forall a b. (a -> b) -> a -> b
$ \forall r. Eff es r -> IO r
unlift -> do
  forall a. MVar a -> (a -> IO a) -> IO ()
M.modifyMVarMasked_ MVar a
var forall a b. (a -> b) -> a -> b
$ \a
a0 -> do
    a
a <- forall r. Eff es r -> IO r
unlift forall a b. (a -> b) -> a -> b
$ a -> Eff es a
f a
a0
    a
a seq :: forall a b. a -> b -> b
`seq` forall (f :: Type -> Type) a. Applicative f => a -> f a
pure a
a

-- | Lifted 'M.modifyMVarMasked' that evaluates the new value to WHNF.
modifyMVarMasked :: Concurrent :> es => MVar a -> (a -> Eff es (a, b)) -> Eff es b
modifyMVarMasked :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
MVar a -> (a -> Eff es (a, b)) -> Eff es b
modifyMVarMasked MVar a
var a -> Eff es (a, b)
f = forall (es :: [Effect]) a.
((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
reallyUnsafeUnliftIO forall a b. (a -> b) -> a -> b
$ \forall r. Eff es r -> IO r
unlift -> do
  forall a b. MVar a -> (a -> IO (a, b)) -> IO b
M.modifyMVarMasked MVar a
var forall a b. (a -> b) -> a -> b
$ \a
a0 -> do
    (a, b)
a <- forall r. Eff es r -> IO r
unlift forall a b. (a -> b) -> a -> b
$ a -> Eff es (a, b)
f a
a0
    (a, b)
a seq :: forall a b. a -> b -> b
`seq` forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (a, b)
a

-- | Lifted 'M.mkWeakMVar'.
mkWeakMVar :: Concurrent :> es => MVar a -> Eff es () -> Eff es (Weak (MVar a))
mkWeakMVar :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
MVar a -> Eff es () -> Eff es (Weak (MVar a))
mkWeakMVar MVar a
var Eff es ()
f = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  -- The finalizer can run at any point and in any thread.
  forall a. MVar a -> IO () -> IO (Weak (MVar a))
M.mkWeakMVar MVar a
var forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es ()
f forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es