module GHC.ForeignPtr
(
ForeignPtr(..),
- newForeignPtr,
+ FinalizerPtr,
+ newForeignPtr_,
mallocForeignPtr,
mallocForeignPtrBytes,
addForeignPtrFinalizer,
touchForeignPtr,
- withForeignPtr,
- foreignPtrToPtr,
+ unsafeForeignPtrToPtr,
castForeignPtr,
newConcForeignPtr,
addForeignPtrConcFinalizer,
import Control.Monad ( sequence_ )
import Foreign.Ptr
import Foreign.Storable
-import Data.Dynamic
+import Data.Typeable
import GHC.List ( null )
import GHC.Base
| MallocPtr (MutableByteArray# RealWorld) !(IORef [IO ()])
instance Eq (ForeignPtr a) where
- p == q = foreignPtrToPtr p == foreignPtrToPtr q
+ p == q = unsafeForeignPtrToPtr p == unsafeForeignPtrToPtr q
instance Ord (ForeignPtr a) where
- compare p q = compare (foreignPtrToPtr p) (foreignPtrToPtr q)
+ compare p q = compare (unsafeForeignPtrToPtr p) (unsafeForeignPtrToPtr q)
instance Show (ForeignPtr a) where
- showsPrec p f = showsPrec p (foreignPtrToPtr f)
+ showsPrec p f = showsPrec p (unsafeForeignPtrToPtr f)
-#include "Dynamic.h"
+#include "Typeable.h"
INSTANCE_TYPEABLE1(ForeignPtr,foreignPtrTc,"ForeignPtr")
-newForeignPtr :: Ptr a -> FunPtr (Ptr a -> IO ()) -> IO (ForeignPtr a)
--- ^Turns a plain memory reference into a foreign object by
--- associating a finaliser - a foreign function given by the @FunPtr@
--- - 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
+-- |A Finaliser is represented as a pointer to a foreign function that, at
+-- finalisation time, gets as an argument a plain pointer variant of the
+-- foreign pointer that the finalizer is associated with.
+--
+type FinalizerPtr a = FunPtr (Ptr a -> IO ())
newConcForeignPtr :: Ptr a -> IO () -> IO (ForeignPtr a)
-- ^Turns a plain memory reference into a foreign object
-- The finalizer, when invoked, will run in a separate thread.
--
newConcForeignPtr p finalizer
- = do fObj <- mkForeignPtr p
+ = do fObj <- newForeignPtr_ p
addForeignPtrConcFinalizer fObj finalizer
return fObj
(# s, MallocPtr mbarr# r #)
}
-addForeignPtrFinalizer :: ForeignPtr a -> FunPtr (Ptr a -> IO ()) -> IO ()
+addForeignPtrFinalizer :: FinalizerPtr a -> ForeignPtr a -> IO ()
-- ^This function adds a finaliser to the given foreign object. The
-- finalizer will run /before/ all other finalizers for the same
-- object which have already been registered.
-addForeignPtrFinalizer fptr finalizer =
+addForeignPtrFinalizer finalizer fptr =
addForeignPtrConcFinalizer fptr
- (mkFinalizer finalizer (foreignPtrToPtr fptr))
+ (mkFinalizer finalizer (unsafeForeignPtrToPtr fptr))
addForeignPtrConcFinalizer :: ForeignPtr a -> IO () -> IO ()
-- ^This function adds a finaliser to the given @ForeignPtr@. The
writeIORef r (finalizer : fs)
if (null fs)
then IO $ \s ->
- let p = foreignPtrToPtr f in
+ let p = unsafeForeignPtrToPtr f in
case mkWeak# fo () (foreignPtrFinalizer r p) s of
(# s1, w #) -> (# s1, () #)
else return ()
writeIORef r (finalizer : fs)
if (null fs)
then IO $ \s ->
- let p = foreignPtrToPtr f in
+ let p = unsafeForeignPtrToPtr f in
case mkWeak# fo () (foreignPtrFinalizer r p) s of
(# s1, w #) -> (# s1, () #)
else return ()
foreign import ccall "dynamic"
- mkFinalizer :: FunPtr (Ptr a -> IO ()) -> Ptr a -> IO ()
+ mkFinalizer :: FinalizerPtr a -> Ptr a -> IO ()
foreignPtrFinalizer :: IORef [IO ()] -> Ptr a -> IO ()
foreignPtrFinalizer r p = do
fs <- readIORef r
sequence_ fs
-mkForeignPtr :: Ptr a -> IO (ForeignPtr a) {- not exported -}
-mkForeignPtr (Ptr obj) = do
+newForeignPtr_ :: Ptr a -> IO (ForeignPtr a)
+-- ^Turns a plain memory reference into a foreign pointer that may be
+-- associated with finalizers by using 'addForeignPtrFinalizer'.
+newForeignPtr_ (Ptr obj) = do
r <- newIORef []
IO $ \ s# ->
case mkForeignObj# obj s# of
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'
+-- actions. In particular 'Foreign.ForeignPtr.withForeignPtr'
-- does a 'touchForeignPtr' after it
-- executes the user action.
--
touchForeignPtr (MallocPtr fo r)
= 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
+unsafeForeignPtrToPtr :: 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
+-- argument to 'unsafeForeignPtrToPtr' 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
-- has another usage occurrence.
--
-- To avoid subtle coding errors, hand written marshalling code
--- should preferably use 'withForeignPtr' rather
--- than combinations of 'foreignPtrToPtr' and
+-- should preferably use 'Foreign.ForeignPtr.withForeignPtr' rather
+-- than combinations of 'unsafeForeignPtrToPtr' and
-- 'touchForeignPtr'. However, the later routines
-- are occasionally preferred in tool generated marshalling code.
-foreignPtrToPtr (ForeignPtr fo r) = Ptr (foreignObjToAddr# fo)
-foreignPtrToPtr (MallocPtr fo r) = Ptr (byteArrayContents# (unsafeCoerce# fo))
+unsafeForeignPtrToPtr (ForeignPtr fo r) = Ptr (foreignObjToAddr# fo)
+unsafeForeignPtrToPtr (MallocPtr fo r) = Ptr (byteArrayContents# (unsafeCoerce# fo))
castForeignPtr :: ForeignPtr a -> ForeignPtr b
-- ^This function casts a 'ForeignPtr'