module Ouroboros.Consensus.Util.MonadSTM.NormalForm (
    module LazySTM
  , module Ouroboros.Consensus.Util.MonadSTM.StrictMVar
  , module StrictSTM
  , newEmptyMVar
  , newMVar
  , newTVar
  , newTVarIO
    -- * Temporary
  , uncheckedNewEmptyMVar
  , uncheckedNewMVar
  , uncheckedNewTVarM
  ) where

import           GHC.Stack
import           NoThunks.Class (NoThunks (..), unsafeNoThunks)


import           Ouroboros.Consensus.Util.MonadSTM.StrictMVar hiding
                     (newEmptyMVar, newEmptyMVarWithInvariant, newMVar,
                     newMVarWithInvariant)

import           Control.Concurrent.Class.MonadSTM.Strict.TMVar as StrictSTM hiding
                     (newTMVar, newTMVarIO)
import           Control.Concurrent.Class.MonadSTM.Strict.TVar as StrictSTM hiding
                     (newTVar, newTVarIO, newTVarWithInvariantIO)
-- TODO: use strict versions of 'TQueue' and 'TBQueue'.  Previously the
-- 'Control.Monad.Class.MonadSTM.Strict' was imported which
-- exported lazy 'TQueue' and 'TBQueue',  I (@coot) think that the intention was
-- to use strict versions.
import           Control.Concurrent.Class.MonadSTM.TBQueue as LazySTM
import           Control.Concurrent.Class.MonadSTM.TQueue as LazySTM
import           Control.Monad.Class.MonadSTM as StrictSTM

import qualified Control.Concurrent.Class.MonadSTM.Strict as Strict
import qualified Ouroboros.Consensus.Util.MonadSTM.StrictMVar as Strict

{-------------------------------------------------------------------------------
  Wrappers that check for thunks
-------------------------------------------------------------------------------}

newTVarIO :: (MonadSTM m, HasCallStack, NoThunks a)
          => a -> m (StrictTVar m a)
newTVarIO :: a -> m (StrictTVar m a)
newTVarIO = (a -> Maybe String) -> a -> m (StrictTVar m a)
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
(a -> Maybe String) -> a -> m (StrictTVar m a)
Strict.newTVarWithInvariantIO ((ThunkInfo -> String) -> Maybe ThunkInfo -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ThunkInfo -> String
forall a. Show a => a -> String
show (Maybe ThunkInfo -> Maybe String)
-> (a -> Maybe ThunkInfo) -> a -> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe ThunkInfo
forall a. NoThunks a => a -> Maybe ThunkInfo
unsafeNoThunks)

newTVar :: (MonadSTM m, HasCallStack, NoThunks a)
          => a -> STM m (StrictTVar m a)
newTVar :: a -> STM m (StrictTVar m a)
newTVar = (a -> Maybe String) -> a -> STM m (StrictTVar m a)
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
(a -> Maybe String) -> a -> STM m (StrictTVar m a)
Strict.newTVarWithInvariant ((ThunkInfo -> String) -> Maybe ThunkInfo -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ThunkInfo -> String
forall a. Show a => a -> String
show (Maybe ThunkInfo -> Maybe String)
-> (a -> Maybe ThunkInfo) -> a -> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe ThunkInfo
forall a. NoThunks a => a -> Maybe ThunkInfo
unsafeNoThunks)

newMVar :: (MonadSTM m, HasCallStack, NoThunks a)
        => a -> m (StrictMVar m a)
newMVar :: a -> m (StrictMVar m a)
newMVar = (a -> Maybe String) -> a -> m (StrictMVar m a)
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
(a -> Maybe String) -> a -> m (StrictMVar m a)
Strict.newMVarWithInvariant ((ThunkInfo -> String) -> Maybe ThunkInfo -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ThunkInfo -> String
forall a. Show a => a -> String
show (Maybe ThunkInfo -> Maybe String)
-> (a -> Maybe ThunkInfo) -> a -> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe ThunkInfo
forall a. NoThunks a => a -> Maybe ThunkInfo
unsafeNoThunks)

newEmptyMVar :: (MonadSTM m, NoThunks a) => a -> m (StrictMVar m a)
newEmptyMVar :: a -> m (StrictMVar m a)
newEmptyMVar = (a -> Maybe String) -> a -> m (StrictMVar m a)
forall (m :: * -> *) a.
MonadSTM m =>
(a -> Maybe String) -> a -> m (StrictMVar m a)
Strict.newEmptyMVarWithInvariant ((ThunkInfo -> String) -> Maybe ThunkInfo -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ThunkInfo -> String
forall a. Show a => a -> String
show (Maybe ThunkInfo -> Maybe String)
-> (a -> Maybe ThunkInfo) -> a -> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe ThunkInfo
forall a. NoThunks a => a -> Maybe ThunkInfo
unsafeNoThunks)

{-------------------------------------------------------------------------------
  Unchecked wrappers (where we don't check for thunks)

  These will eventually be removed.
-------------------------------------------------------------------------------}

uncheckedNewTVarM :: MonadSTM m => a -> m (StrictTVar m a)
uncheckedNewTVarM :: a -> m (StrictTVar m a)
uncheckedNewTVarM = a -> m (StrictTVar m a)
forall (m :: * -> *) a. MonadSTM m => a -> m (StrictTVar m a)
Strict.newTVarIO

uncheckedNewMVar :: MonadSTM m => a -> m (StrictMVar m a)
uncheckedNewMVar :: a -> m (StrictMVar m a)
uncheckedNewMVar = a -> m (StrictMVar m a)
forall (m :: * -> *) a. MonadSTM m => a -> m (StrictMVar m a)
Strict.newMVar

uncheckedNewEmptyMVar :: MonadSTM m => a -> m (StrictMVar m a)
uncheckedNewEmptyMVar :: a -> m (StrictMVar m a)
uncheckedNewEmptyMVar = a -> m (StrictMVar m a)
forall (m :: * -> *) a. MonadSTM m => a -> m (StrictMVar m a)
Strict.newEmptyMVar