{-|
Module:             STM.Base
Description:        Lifted STM operations.
Copyright:          © 2017 All rights reserved.
License:            GPL-3
Maintainer:         Evan Cofsky <evan@theunixman.com>
Stability:          experimental
Portability:        POSIX
-}

module STM.Base (
    module IO.Base,
    module Control.Concurrent.STM.TVar,
    module Control.Concurrent.STM.TMVar,
    module Control.Concurrent.STM.TBChan,
    STM,
    atomically,
    newTVarIO,
    newTMVarIO,
    newEmptyTMVarIO,
    newTBChanIO,
    newTBChan
    ) where

import Lawless
import IO.Base
import Control.Concurrent.STM (STM)
import qualified Control.Concurrent.STM as STM
import qualified Control.Concurrent.STM.TVar as TVar
import Control.Concurrent.STM.TVar (TVar, readTVar, writeTVar,  modifyTVar)
import qualified Control.Concurrent.STM.TMVar as TMVar
import Control.Concurrent.STM.TMVar (TMVar, readTMVar)
import qualified Control.Concurrent.STM.TBChan as TBChan
import Control.Concurrent.STM.TBChan (
    TBChan, readTBChan, writeTBChan, isEmptyTBChan
    )

-- | 'STM.atomically' lifted to 'MonadBase' 'IO'.
atomically :: MonadBase IO m => STM α -> m α
atomically = liftBase ∘ STM.atomically

-- | 'newTVarIO' at the top level, lifted.
newTVarIO ∷ MonadBase IO m ⇒ a → m (TVar a)
newTVarIO = liftBase ∘ TVar.newTVarIO

-- | 'newTMVarIO' at the top level, lifted.
newTMVarIO ∷ MonadBase IO m ⇒ a → m (TMVar a)
newTMVarIO = liftBase ∘ TMVar.newTMVarIO

-- | 'newTMVarIO' at the top level, lifted.
newEmptyTMVarIO ∷ MonadBase IO m ⇒ m (TMVar a)
newEmptyTMVarIO = liftBase TMVar.newEmptyTMVarIO

newtype BoundedLength = BoundedLength Word64
    deriving (Eq, Ord, Show, Bounded, Enum, Num, Integral, Real)

-- | 'newTBChanIO' at the top level, lifted, only with a saturated length.
newTBChanIO ∷ (MonadBase IO m, Integral l) ⇒ l → m (TBChan a)
newTBChanIO =
    liftBase ∘ TBChan.newTBChanIO ∘ max 0 ∘ fromIntegral

newTBChan ∷ Integral l ⇒ l → STM (TBChan a)
newTBChan = TBChan.newTBChan ∘ max 0 ∘ fromIntegral