    {-# LANGUAGE CPP #-}
    -- | This was previously known as the Resource monad. However, that term is
    -- confusing next to the ResourceT transformer, so it has been renamed.

    module Data.Acquire
        ( Acquire
    -- * Example usage of 'Acquire' for allocating a resource and freeing it up.
    --
    -- | The code makes use of 'mkAcquire' to create an 'Acquire' and uses 'allocateAcquire' to allocate the resource and register an action to free up the resource.
    --
    -- === __Reproducible Stack code snippet__
    --
    -- > #!/usr/bin/env stack
    -- > {- stack
    -- >      --resolver lts-10.0
    -- >      --install-ghc
    -- >      runghc
    -- >      --package resourcet
    -- > -}
    -- >
    -- > {-#LANGUAGE ScopedTypeVariables#-}
    -- >
    -- > import Data.Acquire
    -- > import Control.Monad.Trans.Resource
    -- > import Control.Monad.IO.Class
    -- >
    -- > main :: IO ()
    -- > main = runResourceT $ do
    -- >     let (ack :: Acquire Int) = mkAcquire (do
    -- >                           putStrLn "Enter some number"
    -- >                           readLn) (\i -> putStrLn $ "Freeing scarce resource: " ++ show i)
    -- >     (releaseKey, resource) <- allocateAcquire ack
    -- >     doSomethingDangerous resource
    -- >     liftIO $ putStrLn $ "Going to release resource immediately: " ++ show resource
    -- >     release releaseKey
    -- >     somethingElse
    -- >
    -- > doSomethingDangerous :: Int -> ResourceT IO ()
    -- > doSomethingDangerous i =
    -- >     liftIO $ putStrLn $ "5 divided by " ++ show i ++ " is " ++ show (5 `div` i)
    -- >
    -- > somethingElse :: ResourceT IO ()
    -- > somethingElse = liftIO $ putStrLn
    -- >     "This could take a long time, don't delay releasing the resource!"
    --
    -- Execution output:
    --
    -- > ~ $ stack code.hs
    -- > Enter some number
    -- > 3
    -- > 5 divided by 3 is 1
    -- > Going to release resource immediately: 3
    -- > Freeing scarce resource: 3
    -- > This could take a long time, don't delay releasing the resource!
    -- >
    -- > ~ $ stack code.hs
    -- > Enter some number
    -- > 0
    -- > 5 divided by 0 is Freeing scarce resource: 0
    -- > code.hs: divide by zero
    --
        , with
        , withAcquire
        , mkAcquire
        , mkAcquireType
        , allocateAcquire
        , ReleaseType (..)
        ) where

    import Control.Monad.Trans.Resource.Internal
    import Data.Acquire.Internal
    import Control.Monad.IO.Unlift (MonadIO (..), MonadUnliftIO)
    import qualified Control.Exception as E

    -- | Allocate a resource and register an action with the @MonadResource@ to
    -- free the resource.
    --
    -- @since 1.1.0
    allocateAcquire :: MonadResource m => Acquire a -> m (ReleaseKey, a)
    allocateAcquire :: forall (m :: * -> *) a.
    MonadResource m =>
    Acquire a -> m (ReleaseKey, a)
    allocateAcquire = ResourceT IO (ReleaseKey, a) -> m (ReleaseKey, a)
    forall a. ResourceT IO a -> m a
    forall (m :: * -> *) a. MonadResource m => ResourceT IO a -> m a
    liftResourceT (ResourceT IO (ReleaseKey, a) -> m (ReleaseKey, a))
    -> (Acquire a -> ResourceT IO (ReleaseKey, a))
    -> Acquire a
    -> m (ReleaseKey, a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Acquire a -> ResourceT IO (ReleaseKey, a)
    forall a. Acquire a -> ResourceT IO (ReleaseKey, a)
    allocateAcquireRIO

    allocateAcquireRIO :: Acquire a -> ResourceT IO (ReleaseKey, a)
    allocateAcquireRIO :: forall a. Acquire a -> ResourceT IO (ReleaseKey, a)
    allocateAcquireRIO (Acquire (forall b. IO b -> IO b) -> IO (Allocated a)
    f) = (IORef ReleaseMap -> IO (ReleaseKey, a))
    -> ResourceT IO (ReleaseKey, a)
    forall (m :: * -> *) a. (IORef ReleaseMap -> m a) -> ResourceT m a
    ResourceT ((IORef ReleaseMap -> IO (ReleaseKey, a))
     -> ResourceT IO (ReleaseKey, a))
    -> (IORef ReleaseMap -> IO (ReleaseKey, a))
    -> ResourceT IO (ReleaseKey, a)
    forall a b. (a -> b) -> a -> b
    $ \IORef ReleaseMap
    istate -> IO (ReleaseKey, a) -> IO (ReleaseKey, a)
    forall b. IO b -> IO b
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (ReleaseKey, a) -> IO (ReleaseKey, a))
    -> IO (ReleaseKey, a) -> IO (ReleaseKey, a)
    forall a b. (a -> b) -> a -> b
    $ ((forall b. IO b -> IO b) -> IO (ReleaseKey, a))
    -> IO (ReleaseKey, a)
    forall b. ((forall b. IO b -> IO b) -> IO b) -> IO b
    E.mask (((forall b. IO b -> IO b) -> IO (ReleaseKey, a))
     -> IO (ReleaseKey, a))
    -> ((forall b. IO b -> IO b) -> IO (ReleaseKey, a))
    -> IO (ReleaseKey, a)
    forall a b. (a -> b) -> a -> b
    $ \forall b. IO b -> IO b
    restore -> do
        Allocated a free <- (forall b. IO b -> IO b) -> IO (Allocated a)
    f IO b -> IO b
    forall b. IO b -> IO b
    restore
        key <- registerType istate free
        return (key, a)

    -- | Longer name for 'with', in case @with@ is not obvious enough in context.
    --
    -- @since 1.2.0
    withAcquire :: MonadUnliftIO m => Acquire a -> (a -> m b) -> m b
    withAcquire :: forall (m :: * -> *) a b.
    MonadUnliftIO m =>
    Acquire a -> (a -> m b) -> m b
    withAcquire = Acquire a -> (a -> m b) -> m b
    forall (m :: * -> *) a b.
    MonadUnliftIO m =>
    Acquire a -> (a -> m b) -> m b
    with
    {-# INLINE withAcquire #-}