-- | Unlifted "Control.Concurrent.QSemN".
--
-- @since 0.2.14
module UnliftIO.QSemN
  ( QSemN
  , newQSemN
  , waitQSemN
  , signalQSemN
  , withQSemN
  ) where

import Control.Concurrent.QSemN (QSemN)
import Control.Monad.IO.Unlift
import UnliftIO.Exception
import qualified Control.Concurrent.QSemN as Q

-- | Lifted 'Q.newQSemN'.
--
-- @since 0.2.14
newQSemN :: MonadIO m => Int -> m QSemN
newQSemN :: forall (m :: * -> *). MonadIO m => Int -> m QSemN
newQSemN = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> IO QSemN
Q.newQSemN

-- | Lifted 'Q.waitQSemN'.
--
-- @since 0.2.14
waitQSemN :: MonadIO m => QSemN -> Int -> m ()
waitQSemN :: forall (m :: * -> *). MonadIO m => QSemN -> Int -> m ()
waitQSemN QSemN
x = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. QSemN -> Int -> IO ()
Q.waitQSemN QSemN
x

-- | Lifted 'Q.signalQSemN'.
--
-- @since 0.2.14
signalQSemN :: MonadIO m => QSemN -> Int -> m ()
signalQSemN :: forall (m :: * -> *). MonadIO m => QSemN -> Int -> m ()
signalQSemN QSemN
x = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. QSemN -> Int -> IO ()
Q.signalQSemN QSemN
x

-- | 'withQSemN' is an exception-safe wrapper for performing the
-- provided operation while holding N unit of value from the semaphore.
-- It ensures the semaphore cannot be leaked if there are exceptions.
--
-- @since 0.2.14
{-# INLINE withQSemN #-}
withQSemN :: MonadUnliftIO m => QSemN -> Int -> m a -> m a
withQSemN :: forall (m :: * -> *) a.
MonadUnliftIO m =>
QSemN -> Int -> m a -> m a
withQSemN QSemN
x Int
n m a
io = forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO forall a b. (a -> b) -> a -> b
$ \forall a. m a -> IO a
run ->
  forall (m :: * -> *) a b c.
MonadUnliftIO m =>
m a -> m b -> m c -> m c
bracket_ (forall (m :: * -> *). MonadIO m => QSemN -> Int -> m ()
waitQSemN QSemN
x Int
n) (forall (m :: * -> *). MonadIO m => QSemN -> Int -> m ()
signalQSemN QSemN
x Int
n) (forall a. m a -> IO a
run m a
io)