-- |Lock effect, Internal
module Polysemy.Conc.Effect.Lock where

-- |An exclusive lock or mutex, protecting a region from concurrent access.
data Lock :: Effect where
  -- |Run an action if the lock is available, block otherwise.
  Lock :: m a -> Lock m a
  -- |Run the second action if the lock is available, or the first action otherwise.
  LockOr :: m a -> m a -> Lock m a

makeSem_ ''Lock

-- |Run an action if the lock is available, block otherwise.
lock ::
   r a .
  Member Lock r =>
  Sem r a ->
  Sem r a

-- |Run an action if the lock is available, block otherwise.
lockOr ::
   r a .
  Member Lock r =>
  Sem r a ->
  Sem r a ->
  Sem r a

-- |Run an action if the lock is available, skip and return 'Nothing' otherwise.
lockOrSkip ::
   r a .
  Member Lock r =>
  Sem r a ->
  Sem r (Maybe a)
lockOrSkip :: forall (r :: EffectRow) a.
Member Lock r =>
Sem r a -> Sem r (Maybe a)
lockOrSkip Sem r a
ma =
  Sem r (Maybe a) -> Sem r (Maybe a) -> Sem r (Maybe a)
forall (r :: EffectRow) a.
Member Lock r =>
Sem r a -> Sem r a -> Sem r a
lockOr (Maybe a -> Sem r (Maybe a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe a
forall a. Maybe a
Nothing) (a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> Sem r a -> Sem r (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Sem r a
ma)
{-# inline lockOrSkip #-}

-- |Run an action if the lock is available, skip otherwise.
-- Return @()@.
lockOrSkip_ ::
   r a .
  Member Lock r =>
  Sem r a ->
  Sem r ()
lockOrSkip_ :: forall (r :: EffectRow) a. Member Lock r => Sem r a -> Sem r ()
lockOrSkip_ Sem r a
ma =
  Sem r () -> Sem r () -> Sem r ()
forall (r :: EffectRow) a.
Member Lock r =>
Sem r a -> Sem r a -> Sem r a
lockOr Sem r ()
forall (f :: * -> *). Applicative f => f ()
unit (Sem r a -> Sem r ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void Sem r a
ma)
{-# inline lockOrSkip_ #-}