{-# OPTIONS_HADDOCK not-home #-}

-- |
-- Module      :  GHC.ForeignPtr
-- Copyright   :  (c) The University of Glasgow, 1992-2003
-- License     :  see libraries/base/LICENSE
--
-- Maintainer  :  ghc-devs@haskell.org
-- Stability   :  internal
-- Portability :  non-portable (GHC extensions)
--
-- GHC's implementation of the 'ForeignPtr' data type.
--

module GHC.ForeignPtr
  (
        -- * Types
        ForeignPtr(..),
        ForeignPtrContents(..),
        Finalizers(..),
        FinalizerPtr,
        FinalizerEnvPtr,
        -- * Create
        newForeignPtr_,
        mallocForeignPtr,
        mallocPlainForeignPtr,
        mallocForeignPtrBytes,
        mallocPlainForeignPtrBytes,
        mallocForeignPtrAlignedBytes,
        mallocPlainForeignPtrAlignedBytes,
        newConcForeignPtr,
        -- * Add Finalizers
        addForeignPtrFinalizer,
        addForeignPtrFinalizerEnv,
        addForeignPtrConcFinalizer,
        -- * Conversion
        unsafeForeignPtrToPtr,
        castForeignPtr,
        plusForeignPtr,
        -- * Control over lifetype
        withForeignPtr,
        unsafeWithForeignPtr,
        touchForeignPtr,
        -- * Finalization
        finalizeForeignPtr
        -- * Commentary
        -- $commentary
  ) where

import GHC.Internal.ForeignPtr

{- $commentary

This is a high-level overview of how 'ForeignPtr' works.
The implementation of 'ForeignPtr' must accomplish several goals:

1. Invoke a finalizer once a foreign pointer becomes unreachable.
2. Support augmentation of finalizers, i.e. 'addForeignPtrFinalizer'.
   As a motivating example, suppose that the payload of a foreign
   pointer is C struct @bar@ that has an optionally NULL pointer field
   @foo@ to an unmanaged heap object. Initially, @foo@ is NULL, and
   later the program uses @malloc@, initializes the object, and assigns
   @foo@ the address returned by @malloc@. When the foreign pointer
   becomes unreachable, it is now necessary to first @free@ the object
   pointed to by @foo@ and then invoke whatever finalizer was associated
   with @bar@. That is, finalizers must be invoked in the opposite order
   they are added.
3. Allow users to invoke a finalizer promptly if they know that the
   foreign pointer is unreachable, i.e. 'finalizeForeignPtr'.

How can these goals be accomplished? Goal 1 suggests that weak references
and finalizers (via 'Weak#' and 'mkWeak#') are necessary. But how should
they be used and what should their key be?  Certainly not 'ForeignPtr' or
'ForeignPtrContents'. See the warning in "GHC.Weak" about weak pointers with
lifted (non-primitive) keys. The two finalizer-supporting data constructors of
'ForeignPtr' have an @'IORef' 'Finalizers'@ (backed by 'MutVar#') field.
This gets used in two different ways depending on the kind of finalizer:

* 'HaskellFinalizers': The first @addForeignPtrConcFinalizer_@ call uses
  'mkWeak#' to attach the finalizer @foreignPtrFinalizer@ to the 'MutVar#'.
  The resulting 'Weak#' is discarded (see @addForeignPtrConcFinalizer_@).
  Subsequent calls to @addForeignPtrConcFinalizer_@ (goal 2) just add
  finalizers onto the list in the 'HaskellFinalizers' data constructor.
* 'CFinalizers': The first 'addForeignPtrFinalizer' call uses
  'mkWeakNoFinalizer#' to create a 'Weak#'. The 'Weak#' is preserved in the
  'CFinalizers' data constructor. Both the first call and subsequent
  calls (goal 2) use 'addCFinalizerToWeak#' to attach finalizers to the
  'Weak#' itself. Also, see Note [MallocPtr finalizers] for discussion of
  the key and value of this 'Weak#'.

In either case, the runtime invokes the appropriate finalizers when the
'ForeignPtr' becomes unreachable.
-}