{-# LANGUAGE BangPatterns       #-}
{-# LANGUAGE ExplicitNamespaces #-}
{-# LANGUAGE GADTs              #-}
{-# LANGUAGE TypeOperators      #-}

-- | This module corresponds to `Control.Concurrent.STM.TMVar` in "stm" package
--
module Control.Concurrent.Class.MonadSTM.Strict.TMVar
  ( -- * StrictTMVar
    StrictTMVar
  , LazyTMVar
  , toLazyTMVar
  , fromLazyTMVar
  , castStrictTMVar
  , newTMVar
  , newEmptyTMVar
  , newTMVarIO
  , newEmptyTMVarIO
  , takeTMVar
  , tryTakeTMVar
  , putTMVar
  , tryPutTMVar
  , readTMVar
  , tryReadTMVar
  , swapTMVar
  , isEmptyTMVar
    -- * MonadLabelledSTM
  , labelTMVar
  , labelTMVarIO
    -- * MonadTraceSTM
  , traceTMVar
  , traceTMVarIO
  ) where


import qualified Control.Concurrent.Class.MonadSTM.TMVar as Lazy
import           Control.Monad.Class.MonadSTM hiding (traceTMVar, traceTMVarIO)


type LazyTMVar   m = Lazy.TMVar m

-- | 'TMVar' that keeps its value in WHNF at all times
--
-- Does not support an invariant: if the invariant would not be satisfied,
-- we would not be able to put a value into an empty TMVar, which would lead
-- to very hard to debug bugs where code is blocked indefinitely.
newtype StrictTMVar m a = StrictTMVar { forall (m :: * -> *) a. StrictTMVar m a -> LazyTMVar m a
toLazyTMVar :: LazyTMVar m a }

fromLazyTMVar :: LazyTMVar m a -> StrictTMVar m a
fromLazyTMVar :: forall (m :: * -> *) a. LazyTMVar m a -> StrictTMVar m a
fromLazyTMVar = forall (m :: * -> *) a. LazyTMVar m a -> StrictTMVar m a
StrictTMVar

labelTMVar :: MonadLabelledSTM m => StrictTMVar m a -> String -> STM m ()
labelTMVar :: forall (m :: * -> *) a.
MonadLabelledSTM m =>
StrictTMVar m a -> String -> STM m ()
labelTMVar (StrictTMVar LazyTMVar m a
tvar) = forall (m :: * -> *) a.
MonadLabelledSTM m =>
TMVar m a -> String -> STM m ()
Lazy.labelTMVar LazyTMVar m a
tvar

labelTMVarIO :: MonadLabelledSTM m => StrictTMVar m a -> String -> m ()
labelTMVarIO :: forall (m :: * -> *) a.
MonadLabelledSTM m =>
StrictTMVar m a -> String -> m ()
labelTMVarIO StrictTMVar m a
v = forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a.
MonadLabelledSTM m =>
StrictTMVar m a -> String -> STM m ()
labelTMVar StrictTMVar m a
v

traceTMVar :: MonadTraceSTM m
           => proxy m
           -> StrictTMVar m a
           -> (Maybe (Maybe a) -> (Maybe a) -> InspectMonad m TraceValue)
           -> STM m ()
traceTMVar :: forall (m :: * -> *) (proxy :: (* -> *) -> *) a.
MonadTraceSTM m =>
proxy m
-> StrictTMVar m a
-> (Maybe (Maybe a) -> Maybe a -> InspectMonad m TraceValue)
-> STM m ()
traceTMVar proxy m
p (StrictTMVar LazyTMVar m a
var) = forall (m :: * -> *) (proxy :: (* -> *) -> *) a.
MonadTraceSTM m =>
proxy m
-> TMVar m a
-> (Maybe (Maybe a) -> Maybe a -> InspectMonad m TraceValue)
-> STM m ()
Lazy.traceTMVar proxy m
p LazyTMVar m a
var

traceTMVarIO :: MonadTraceSTM m
             => StrictTMVar m a
             -> (Maybe (Maybe a) -> (Maybe a) -> InspectMonad m TraceValue)
             -> m ()
traceTMVarIO :: forall (m :: * -> *) a.
MonadTraceSTM m =>
StrictTMVar m a
-> (Maybe (Maybe a) -> Maybe a -> InspectMonad m TraceValue)
-> m ()
traceTMVarIO (StrictTMVar LazyTMVar m a
var) = forall (m :: * -> *) a.
MonadTraceSTM m =>
TMVar m a
-> (Maybe (Maybe a) -> Maybe a -> InspectMonad m TraceValue)
-> m ()
Lazy.traceTMVarIO LazyTMVar m a
var

castStrictTMVar :: LazyTMVar m ~ LazyTMVar n
                => StrictTMVar m a -> StrictTMVar n a
castStrictTMVar :: forall (m :: * -> *) (n :: * -> *) a.
(LazyTMVar m ~ LazyTMVar n) =>
StrictTMVar m a -> StrictTMVar n a
castStrictTMVar (StrictTMVar LazyTMVar m a
var) = forall (m :: * -> *) a. LazyTMVar m a -> StrictTMVar m a
StrictTMVar LazyTMVar m a
var

newTMVar :: MonadSTM m => a -> STM m (StrictTMVar m a)
newTMVar :: forall (m :: * -> *) a. MonadSTM m => a -> STM m (StrictTMVar m a)
newTMVar !a
a = forall (m :: * -> *) a. LazyTMVar m a -> StrictTMVar m a
StrictTMVar forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a. MonadSTM m => a -> STM m (TMVar m a)
Lazy.newTMVar a
a

newTMVarIO :: MonadSTM m => a -> m (StrictTMVar m a)
newTMVarIO :: forall (m :: * -> *) a. MonadSTM m => a -> m (StrictTMVar m a)
newTMVarIO !a
a = forall (m :: * -> *) a. LazyTMVar m a -> StrictTMVar m a
StrictTMVar forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a. MonadSTM m => a -> m (TMVar m a)
Lazy.newTMVarIO a
a

newEmptyTMVar :: MonadSTM m => STM m (StrictTMVar m a)
newEmptyTMVar :: forall (m :: * -> *) a. MonadSTM m => STM m (StrictTMVar m a)
newEmptyTMVar = forall (m :: * -> *) a. LazyTMVar m a -> StrictTMVar m a
StrictTMVar forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a. MonadSTM m => STM m (TMVar m a)
Lazy.newEmptyTMVar

newEmptyTMVarIO :: MonadSTM m => m (StrictTMVar m a)
newEmptyTMVarIO :: forall (m :: * -> *) a. MonadSTM m => m (StrictTMVar m a)
newEmptyTMVarIO = forall (m :: * -> *) a. LazyTMVar m a -> StrictTMVar m a
StrictTMVar forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a. MonadSTM m => m (TMVar m a)
Lazy.newEmptyTMVarIO

takeTMVar :: MonadSTM m => StrictTMVar m a -> STM m a
takeTMVar :: forall (m :: * -> *) a. MonadSTM m => StrictTMVar m a -> STM m a
takeTMVar (StrictTMVar LazyTMVar m a
tmvar) = forall (m :: * -> *) a. MonadSTM m => TMVar m a -> STM m a
Lazy.takeTMVar LazyTMVar m a
tmvar

tryTakeTMVar :: MonadSTM m => StrictTMVar m a -> STM m (Maybe a)
tryTakeTMVar :: forall (m :: * -> *) a.
MonadSTM m =>
StrictTMVar m a -> STM m (Maybe a)
tryTakeTMVar (StrictTMVar LazyTMVar m a
tmvar) = forall (m :: * -> *) a. MonadSTM m => TMVar m a -> STM m (Maybe a)
Lazy.tryTakeTMVar LazyTMVar m a
tmvar

putTMVar :: MonadSTM m => StrictTMVar m a -> a -> STM m ()
putTMVar :: forall (m :: * -> *) a.
MonadSTM m =>
StrictTMVar m a -> a -> STM m ()
putTMVar (StrictTMVar LazyTMVar m a
tmvar) !a
a = forall (m :: * -> *) a. MonadSTM m => TMVar m a -> a -> STM m ()
Lazy.putTMVar LazyTMVar m a
tmvar a
a

tryPutTMVar :: MonadSTM m => StrictTMVar m a -> a -> STM m Bool
tryPutTMVar :: forall (m :: * -> *) a.
MonadSTM m =>
StrictTMVar m a -> a -> STM m Bool
tryPutTMVar (StrictTMVar LazyTMVar m a
tmvar) !a
a = forall (m :: * -> *) a. MonadSTM m => TMVar m a -> a -> STM m Bool
Lazy.tryPutTMVar LazyTMVar m a
tmvar a
a

readTMVar :: MonadSTM m => StrictTMVar m a -> STM m a
readTMVar :: forall (m :: * -> *) a. MonadSTM m => StrictTMVar m a -> STM m a
readTMVar (StrictTMVar LazyTMVar m a
tmvar) = forall (m :: * -> *) a. MonadSTM m => TMVar m a -> STM m a
Lazy.readTMVar LazyTMVar m a
tmvar

tryReadTMVar :: MonadSTM m => StrictTMVar m a -> STM m (Maybe a)
tryReadTMVar :: forall (m :: * -> *) a.
MonadSTM m =>
StrictTMVar m a -> STM m (Maybe a)
tryReadTMVar (StrictTMVar LazyTMVar m a
tmvar) = forall (m :: * -> *) a. MonadSTM m => TMVar m a -> STM m (Maybe a)
Lazy.tryReadTMVar LazyTMVar m a
tmvar

swapTMVar :: MonadSTM m => StrictTMVar m a -> a -> STM m a
swapTMVar :: forall (m :: * -> *) a.
MonadSTM m =>
StrictTMVar m a -> a -> STM m a
swapTMVar (StrictTMVar LazyTMVar m a
tmvar) !a
a = forall (m :: * -> *) a. MonadSTM m => TMVar m a -> a -> STM m a
Lazy.swapTMVar LazyTMVar m a
tmvar a
a

isEmptyTMVar :: MonadSTM m => StrictTMVar m a -> STM m Bool
isEmptyTMVar :: forall (m :: * -> *) a. MonadSTM m => StrictTMVar m a -> STM m Bool
isEmptyTMVar (StrictTMVar LazyTMVar m a
tmvar) = forall (m :: * -> *) a. MonadSTM m => TMVar m a -> STM m Bool
Lazy.isEmptyTMVar LazyTMVar m a
tmvar