packages feed

netease-fm-1.2.2: lib/Control/Concurrent/STM/Lock.hs

module Control.Concurrent.STM.Lock (
  Lock
, LockState (..)
, newLock
, newLockIO
, newAcquiredLock
, newAcquiredLockIO
, acquireLock
, releaseLock
, waitLock
, viewLock
) where

import Control.Concurrent.STM
import Control.Monad (void)

newtype Lock = Lock { un :: TMVar () }
data LockState = Acquired | Released deriving (Eq)

newLock :: STM Lock
newLock = Lock <$> newTMVar ()

newLockIO :: IO Lock
newLockIO = Lock <$> newTMVarIO ()

newAcquiredLock :: STM Lock
newAcquiredLock = Lock <$> newEmptyTMVar

newAcquiredLockIO :: IO Lock
newAcquiredLockIO = Lock <$> newEmptyTMVarIO

acquireLock :: Lock -> STM ()
acquireLock = takeTMVar . un

releaseLock :: Lock -> STM ()
releaseLock (Lock lock) = void $ tryPutTMVar lock ()

waitLock :: Lock -> LockState -> STM ()
waitLock (Lock lock) state = case state of
  Acquired -> putTMVar lock () >> takeTMVar lock
  Released -> takeTMVar lock >> putTMVar lock ()

viewLock :: Lock -> STM LockState
viewLock (Lock lock) = do
  locked <- isEmptyTMVar lock
  return $ if locked then Acquired else Released