{-# 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. -}