packages feed

liblawless-0.23.0: Source/STM/Flag.hs

{-|
Module:             STM.Flag
Description:        A flag plus a function to run an 'Async' and lower the flag when it's started.
Copyright:          © 2017 All rights reserved.
License:            GPL-3
Maintainer:         Evan Cofsky <evan@theunixman.com>
Stability:          experimental
Portability:        POSIX
-}

module STM.Flag where

import Lawless
import Control.Concurrent.Async.Lifted
import Control.Concurrent.STM.TSem
import STM.Base

-- | A 'Flag' used for mutexes.
newtype Flag = Flag TSem

-- | Creates a new 'Flag' in the held state.
newFlag ∷ (MonadBase IO m) ⇒ m Flag
newFlag = Flag <$> atomically (newTSem 0)

-- | Waits for a 'Flag' to be unheld.
waitFlag ∷ Flag → STM ()
waitFlag (Flag s) = waitTSem s

-- | Signals a 'Flag' has been released.
lowerFlag ∷ Flag → STM ()
lowerFlag (Flag s) = signalTSem s

-- | Runs @f@ in a new 'Async', waiting for the 'Async' to start
-- before continuing.
run ∷ MonadBaseControl IO m ⇒ m a → m (Async (StM m a))
run f = do
    g ← newFlag
    a ← async $ do
        atomically $ lowerFlag g
        f
    atomically $ waitFlag g
    return a