-- | Provides a synchronized stack for use in the IO monad
--
-- See also "Control.Concurrent.STM.Stack"
module Control.Concurrent.Stack (
    Stack,
    stackNew,
    stackPush,
    stackPeek,
    stackTryPeek,
    stackPop,
    stackTryPop,
    stackIsEmpty,
    stackSize,
  )
  where

import Control.Monad.STM
import Numeric.Natural

import qualified Control.Concurrent.STM.Stack as STM
import Control.Concurrent.STM.Stack (Stack)

-- | Create new empty Stack
stackNew :: IO (Stack a)
stackNew = atomically STM.stackNew

-- | Push item onto Stack
stackPush :: Stack a -> a -> IO ()
stackPush stack item = atomically (STM.stackPush stack item)

-- | Pop most recently added item without removing from the Stack
stackTryPeek :: Stack a -> IO (Maybe a)
stackTryPeek stack = atomically (STM.stackTryPeek stack)

-- | Pop most recently added item without removing from the Stack
--
-- Blocks if stack is empty
stackPeek :: Stack a -> IO a
stackPeek stack = atomically (STM.stackPeek stack)

-- | Pop most recently added item from Stack
stackTryPop :: Stack a -> IO (Maybe a)
stackTryPop stack = atomically (STM.stackTryPop stack)

-- | Pop most recently added item from Stack
--
-- Blocks if stack is empty
stackPop :: Stack a -> IO a
stackPop stack = atomically (STM.stackPop stack)

-- | Test if stack is empty
stackIsEmpty :: Stack a -> IO Bool
stackIsEmpty stack = atomically (STM.stackIsEmpty stack)

-- | Compute number of elements contained in the Stack
stackSize :: Stack a -> IO Natural
stackSize stack = atomically (STM.stackSize stack)