-- |
-- Module : Foreign.ForeignPtr
-- Copyright : (c) The University of Glasgow 2001
--- License : BSD-style (see the file libraries/core/LICENSE)
+-- License : BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer : ffi@haskell.org
-- Stability : provisional
-- Portability : portable
--
--- This module defines foreign pointers, i.e. addresses with associated
--- finalizers.
+-- 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
- ( ForeignPtr, -- abstract, instance of: Eq
+ (
+ -- * Finalised data pointers
+ ForeignPtr -- abstract, instance of: Eq
, newForeignPtr -- :: Ptr a -> IO () -> IO (ForeignPtr a)
, addForeignPtrFinalizer -- :: ForeignPtr a -> IO () -> IO ()
, withForeignPtr -- :: ForeignPtr a -> (Ptr a -> IO b) -> IO b
import GHC.Base
import GHC.IOBase
import GHC.Num
+import GHC.Ptr ( Ptr(..) )
import GHC.Err
#endif
INSTANCE_TYPEABLE1(ForeignPtr,foreignPtrTc,"ForeignPtr")
#ifdef __GLASGOW_HASKELL__
+-- |The type 'ForeignPtr' represents references to objects that are
+-- maintained in a foreign language, i.e., that are not part of the
+-- data structures usually managed by the Haskell storage manager.
+-- The essential difference between 'ForeignPtr's and vanilla memory
+-- references of type @Ptr a@ is that the former may be associated
+-- with /finalisers/. A finaliser is a routine that is invoked when
+-- the Haskell storage manager detects that - within the Haskell heap
+-- and stack - there are no more references left that are pointing to
+-- the 'ForeignPtr'. Typically, the finaliser will, then, invoke
+-- routines in the foreign language that free the resources bound by
+-- the foreign object.
+--
+-- The 'ForeignPtr' is parameterised in the same way as 'Ptr'. The
+-- type argument of 'ForeignPtr' should normally be an instance of
+-- class 'Storable'.
+--
data ForeignPtr a = ForeignPtr ForeignObj#
+
instance CCallable (ForeignPtr a)
eqForeignPtr :: ForeignPtr a -> ForeignPtr a -> Bool
p /= q = not (eqForeignPtr p q)
newForeignPtr :: Ptr a -> IO () -> IO (ForeignPtr a)
+-- ^Turns a plain memory reference into a foreign object
+-- by associating a finaliser - given by the monadic operation
+-- - with the reference. The finaliser will be executed after
+-- the last reference to the foreign object is dropped. Note
+-- that there is no guarantee on how soon the finaliser is
+-- executed after the last reference was dropped; this depends
+-- on the details of the Haskell storage manager. The only
+-- guarantee is that the finaliser runs before the program
+-- terminates.
newForeignPtr p finalizer
= do fObj <- mkForeignPtr p
addForeignPtrFinalizer fObj finalizer
return fObj
addForeignPtrFinalizer :: ForeignPtr a -> IO () -> IO ()
+-- ^This function adds another finaliser to the given
+-- foreign object. No guarantees are made on the order in
+-- which multiple finalisers for a single object are run.
addForeignPtrFinalizer (ForeignPtr fo) finalizer =
IO $ \s -> case mkWeak# fo () finalizer s of { (# s1, w #) -> (# s1, () #) }
(# s1#, fo# #) -> (# s1#, ForeignPtr fo# #) )
touchForeignPtr :: ForeignPtr a -> IO ()
+-- ^This function ensures that the foreign object in
+-- question is alive at the given place in the sequence of IO
+-- actions. In particular 'withForeignPtr'
+-- does a 'touchForeignPtr' after it
+-- executes the user action.
+--
+-- This function can be used to express liveness
+-- dependencies between 'ForeignPtr's: for
+-- example, if the finalizer for one
+-- 'ForeignPtr' touches a second
+-- 'ForeignPtr', then it is ensured that the
+-- second 'ForeignPtr' will stay alive at
+-- least as long as the first. This can be useful when you
+-- want to manipulate /interior pointers/ to
+-- a foreign structure: you can use
+-- 'touchForeignObj' to express the
+-- requirement that the exterior pointer must not be finalized
+-- until the interior pointer is no longer referenced.
touchForeignPtr (ForeignPtr fo)
= IO $ \s -> case touch# fo s of s -> (# s, () #)
withForeignPtr :: ForeignPtr a -> (Ptr a -> IO b) -> IO b
+-- ^This is a way to look at the pointer living inside a
+-- foreign object. This function takes a function which is
+-- applied to that pointer. The resulting 'IO' action is then
+-- executed. The foreign object is kept alive at least during
+-- the whole action, even if it is not used directly
+-- inside. Note that it is not safe to return the pointer from
+-- the action and use it after the action completes. All uses
+-- of the pointer should be inside the
+-- 'withForeignPtr' bracket. The reason for
+-- this unsafety is the same as for
+-- 'foreignPtrToPtr' below: the finalizer
+-- may run earlier than expected, because the compiler can only
+-- track usage of the 'ForeignPtr' object, not
+-- a 'Ptr' object made from it.
+--
+-- This function is normally used for marshalling data to
+-- or from the object pointed to by the
+-- 'ForeignPtr', using the operations from the
+-- 'Storable' class.
withForeignPtr fo io
= do r <- io (foreignPtrToPtr fo)
touchForeignPtr fo
return r
foreignPtrToPtr :: ForeignPtr a -> Ptr a
+-- ^This function extracts the pointer component of a foreign
+-- pointer. This is a potentially dangerous operations, as if the
+-- argument to 'foreignPtrToPtr' is the last usage
+-- occurence of the given foreign pointer, then its finaliser(s) will
+-- be run, which potentially invalidates the plain pointer just
+-- obtained. Hence, 'touchForeignPtr' must be used
+-- wherever it has to be guaranteed that the pointer lives on - i.e.,
+-- has another usage occurrence.
+--
+-- To avoid subtle coding errors, hand written marshalling code
+-- should preferably use 'withForeignPtr' rather
+-- than combinations of 'foreignPtrToPtr' and
+-- 'touchForeignPtr'. However, the later routines
+-- are occasionally preferred in tool generated marshalling code.
foreignPtrToPtr (ForeignPtr fo) = Ptr (foreignObjToAddr# fo)
+castForeignPtr :: ForeignPtr a -> ForeignPtr b
+-- ^This function casts a 'ForeignPtr'
+-- parameterised by one type into another type.
castForeignPtr (ForeignPtr a) = ForeignPtr a
#endif