ribosome-0.3.0.0: lib/Ribosome/Control/Lock.hs
module Ribosome.Control.Lock where
import Control.Exception.Lifted (finally)
import qualified Control.Lens as Lens (at, view)
import Control.Monad.IO.Class (MonadIO)
import Control.Monad.Trans.Control (MonadBaseControl)
import qualified Data.Map as Map (insert)
import UnliftIO.STM (TMVar, newTMVarIO, tryPutTMVar, tryTakeTMVar)
import Ribosome.Control.Monad.Ribo (MonadRibo, pluginInternalL, pluginInternalModifyL)
import Ribosome.Control.Ribosome (Locks)
import qualified Ribosome.Control.Ribosome as Ribosome (locks)
import qualified Ribosome.Log as Log (debug)
getLocks :: (MonadRibo m, MonadIO m) => m Locks
getLocks =
pluginInternalL Ribosome.locks
inspectLocks :: (MonadRibo m, MonadIO m) => (Locks -> a) -> m a
inspectLocks = (<$> getLocks)
modifyLocks :: MonadRibo m => (Locks -> Locks) -> m ()
modifyLocks =
pluginInternalModifyL Ribosome.locks
getOrCreateLock :: (MonadRibo m, MonadIO m) => Text -> m (TMVar ())
getOrCreateLock key = do
currentLock <- inspectLocks $ Lens.view $ Lens.at key
case currentLock of
Just tv -> return tv
Nothing -> do
tv <- newTMVarIO ()
modifyLocks $ Map.insert key tv
getOrCreateLock key
lockOrSkip ::
MonadRibo m =>
MonadIO m =>
MonadBaseControl IO m =>
Text ->
m () ->
m ()
lockOrSkip key thunk = do
currentLock <- getOrCreateLock key
currentState <- atomically $ tryTakeTMVar currentLock
case currentState of
Just _ -> do
Log.debug $ "locking MVar `" <> key <> "`"
finally thunk $ atomically $ tryPutTMVar currentLock ()
Log.debug $ "unlocking MVar `" <> key <> "`"
Nothing -> return ()