base-4.22.0.0: src/GHC/ForeignPtr.hs
{-# 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.
-}