    {-# LANGUAGE Unsafe #-}
    {-# LANGUAGE NoImplicitPrelude #-}
    {-# OPTIONS_HADDOCK not-home #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Foreign.ForeignPtr.Imp
    -- Copyright   :  (c) The University of Glasgow 2001
    -- License     :  BSD-style (see the file libraries/base/LICENSE)
    --
    -- Maintainer  :  ffi@haskell.org
    -- Stability   :  provisional
    -- Portability :  portable
    --
    -- The 'ForeignPtr' type and operations.  This module is part of the
    -- Foreign Function Interface (FFI) and will usually be imported via
    -- the "Foreign" module.
    --
    -----------------------------------------------------------------------------

    module Foreign.ForeignPtr.Imp
            (
            -- * Finalised data pointers
              ForeignPtr
            , FinalizerPtr
            , FinalizerEnvPtr

            -- ** Basic operations
            , newForeignPtr
            , newForeignPtr_
            , addForeignPtrFinalizer
            , newForeignPtrEnv
            , addForeignPtrFinalizerEnv
            , withForeignPtr
            , finalizeForeignPtr

            -- ** Low-level operations
            , unsafeForeignPtrToPtr
            , touchForeignPtr
            , castForeignPtr
            , plusForeignPtr

            -- ** Allocating managed memory
            , mallocForeignPtr
            , mallocForeignPtrBytes
            , mallocForeignPtrArray
            , mallocForeignPtrArray0
            )
            where

    import Foreign.Ptr
    import Foreign.Storable ( Storable(sizeOf) )

    import GHC.Base
    import GHC.Num
    import GHC.ForeignPtr

    newForeignPtr :: FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
    -- ^Turns a plain memory reference into a foreign pointer, and
    -- associates a finalizer with the reference.  The finalizer will be
    -- executed after the last reference to the foreign object is dropped.
    -- There is no guarantee of promptness, however the finalizer will be
    -- executed before the program exits.
    newForeignPtr :: forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
    newForeignPtr FinalizerPtr a
    finalizer Ptr a
    p
      = do ForeignPtr a
    fObj <- Ptr a -> IO (ForeignPtr a)
    forall a. Ptr a -> IO (ForeignPtr a)
    newForeignPtr_ Ptr a
    p
           FinalizerPtr a -> ForeignPtr a -> IO ()
    forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
    addForeignPtrFinalizer FinalizerPtr a
    finalizer ForeignPtr a
    fObj
           ForeignPtr a -> IO (ForeignPtr a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return ForeignPtr a
    fObj

    -- | This variant of 'newForeignPtr' adds a finalizer that expects an
    -- environment in addition to the finalized pointer.  The environment
    -- that will be passed to the finalizer is fixed by the second argument to
    -- 'newForeignPtrEnv'.
    newForeignPtrEnv ::
        FinalizerEnvPtr env a -> Ptr env -> Ptr a -> IO (ForeignPtr a)
    newForeignPtrEnv :: forall env a.
    FinalizerEnvPtr env a -> Ptr env -> Ptr a -> IO (ForeignPtr a)
    newForeignPtrEnv FinalizerEnvPtr env a
    finalizer Ptr env
    env Ptr a
    p
      = do ForeignPtr a
    fObj <- Ptr a -> IO (ForeignPtr a)
    forall a. Ptr a -> IO (ForeignPtr a)
    newForeignPtr_ Ptr a
    p
           FinalizerEnvPtr env a -> Ptr env -> ForeignPtr a -> IO ()
    forall env a.
    FinalizerEnvPtr env a -> Ptr env -> ForeignPtr a -> IO ()
    addForeignPtrFinalizerEnv FinalizerEnvPtr env a
    finalizer Ptr env
    env ForeignPtr a
    fObj
           ForeignPtr a -> IO (ForeignPtr a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return ForeignPtr a
    fObj

    -- | This function is similar to 'Foreign.Marshal.Array.mallocArray',
    -- but yields a memory area that has a finalizer attached that releases
    -- the memory area.  As with 'mallocForeignPtr', it is not guaranteed that
    -- the block of memory was allocated by 'Foreign.Marshal.Alloc.malloc'.
    mallocForeignPtrArray :: Storable a => Int -> IO (ForeignPtr a)
    mallocForeignPtrArray :: forall a. Storable a => Int -> IO (ForeignPtr a)
    mallocForeignPtrArray  = a -> Int -> IO (ForeignPtr a)
    forall b. Storable b => b -> Int -> IO (ForeignPtr b)
    doMalloc a
    forall a. HasCallStack => a
    undefined
      where
        doMalloc            :: Storable b => b -> Int -> IO (ForeignPtr b)
        doMalloc :: forall b. Storable b => b -> Int -> IO (ForeignPtr b)
    doMalloc b
    dummy Int
    size  = Int -> IO (ForeignPtr b)
    forall a. Int -> IO (ForeignPtr a)
    mallocForeignPtrBytes (Int
    size Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * b -> Int
    forall a. Storable a => a -> Int
    sizeOf b
    dummy)

    -- | This function is similar to 'Foreign.Marshal.Array.mallocArray0',
    -- but yields a memory area that has a finalizer attached that releases
    -- the memory area.  As with 'mallocForeignPtr', it is not guaranteed that
    -- the block of memory was allocated by 'Foreign.Marshal.Alloc.malloc'.
    mallocForeignPtrArray0      :: Storable a => Int -> IO (ForeignPtr a)
    mallocForeignPtrArray0 :: forall a. Storable a => Int -> IO (ForeignPtr a)
    mallocForeignPtrArray0 Int
    size  = Int -> IO (ForeignPtr a)
    forall a. Storable a => Int -> IO (ForeignPtr a)
    mallocForeignPtrArray (Int
    size Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1)