-- | Unlifted "Control.Concurrent.QSem".
--
-- @since 0.2.14
module UnliftIO.QSem
  ( QSem
  , newQSem
  , waitQSem
  , signalQSem
  , withQSem
  ) where

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

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

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

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

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