X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=Foreign%2FForeignPtr.hs;h=b91ffebf52b09f9916f351619400f0a624ceb43d;hb=7a97ec4b12e1fbec5505f82032cf4dc435b5a60c;hp=94c1591494df0c33d8df6ff201146472f7c38a5e;hpb=d2e40014e751abc0915a84401ec2dccfcc1951b4;p=ghc-base.git diff --git a/Foreign/ForeignPtr.hs b/Foreign/ForeignPtr.hs index 94c1591..b91ffeb 100644 --- a/Foreign/ForeignPtr.hs +++ b/Foreign/ForeignPtr.hs @@ -1,4 +1,5 @@ -{-# OPTIONS -fno-implicit-prelude #-} +{-# LANGUAGE CPP, NoImplicitPrelude #-} + ----------------------------------------------------------------------------- -- | -- Module : Foreign.ForeignPtr @@ -17,23 +18,38 @@ module Foreign.ForeignPtr ( - -- * Finalised data pointers - ForeignPtr - , FinalizerPtr + -- * Finalised data pointers + ForeignPtr + , FinalizerPtr +#if defined(__HUGS__) || defined(__GLASGOW_HASKELL__) + , FinalizerEnvPtr +#endif + -- ** Basic operations , newForeignPtr , newForeignPtr_ , addForeignPtrFinalizer - , withForeignPtr - , unsafeForeignPtrToPtr - , touchForeignPtr - , castForeignPtr - - , mallocForeignPtr - , mallocForeignPtrBytes - , mallocForeignPtrArray - , mallocForeignPtrArray0 +#if defined(__HUGS__) || defined(__GLASGOW_HASKELL__) + , newForeignPtrEnv + , addForeignPtrFinalizerEnv +#endif + , withForeignPtr + +#ifdef __GLASGOW_HASKELL__ + , finalizeForeignPtr +#endif + + -- ** Low-level operations + , unsafeForeignPtrToPtr + , touchForeignPtr + , castForeignPtr + + -- ** Allocating managed memory + , mallocForeignPtr + , mallocForeignPtrBytes + , mallocForeignPtrArray + , mallocForeignPtrArray0 ) - where + where import Foreign.Ptr @@ -42,6 +58,7 @@ import NHC.FFI ( ForeignPtr , FinalizerPtr , newForeignPtr + , newForeignPtr_ , addForeignPtrFinalizer , withForeignPtr , unsafeForeignPtrToPtr @@ -57,23 +74,19 @@ import Hugs.ForeignPtr #endif #ifndef __NHC__ -import Foreign.Storable ( Storable(sizeOf) ) +import Foreign.Storable ( Storable(sizeOf) ) #endif #ifdef __GLASGOW_HASKELL__ import GHC.Base -import GHC.IOBase +-- import GHC.IO import GHC.Num -import GHC.Err ( undefined ) +import GHC.Err ( undefined ) import GHC.ForeignPtr #endif #if !defined(__NHC__) && !defined(__GLASGOW_HASKELL__) -import Foreign.Marshal.Alloc ( malloc, mallocBytes, finalizerFree ) -import Data.Dynamic - -#include "Dynamic.h" -INSTANCE_TYPEABLE1(ForeignPtr,foreignPtrTc,"ForeignPtr") +import Foreign.Marshal.Alloc ( malloc, mallocBytes, finalizerFree ) instance Eq (ForeignPtr a) where p == q = unsafeForeignPtrToPtr p == unsafeForeignPtrToPtr q @@ -87,6 +100,17 @@ instance Show (ForeignPtr a) where #ifndef __NHC__ +newForeignPtr :: FinalizerPtr a -> Ptr a -> IO (ForeignPtr a) +-- ^Turns a plain memory reference into a foreign pointer, and +-- associates a finalizer with the reference. The finalizer will be +-- executed after the last reference to the foreign object is dropped. +-- There is no guarantee of promptness, however the finalizer will be +-- executed before the program exits. +newForeignPtr finalizer p + = do fObj <- newForeignPtr_ p + addForeignPtrFinalizer finalizer fObj + return fObj + 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 @@ -97,7 +121,7 @@ withForeignPtr :: ForeignPtr a -> (Ptr a -> IO b) -> IO b -- 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 +-- this unsafeness is the same as for -- 'unsafeForeignPtrToPtr' below: the finalizer -- may run earlier than expected, because the compiler can only -- track usage of the 'ForeignPtr' object, not @@ -113,28 +137,44 @@ withForeignPtr fo io return r #endif /* ! __NHC__ */ -#ifdef __HUGS__ --- temporary aliasing until hugs catches up -unsafeForeignPtrToPtr = foreignPtrToPtr -#endif +#if defined(__HUGS__) || defined(__GLASGOW_HASKELL__) +-- | This variant of 'newForeignPtr' adds a finalizer that expects an +-- environment in addition to the finalized pointer. The environment +-- that will be passed to the finalizer is fixed by the second argument to +-- 'newForeignPtrEnv'. +newForeignPtrEnv :: + FinalizerEnvPtr env a -> Ptr env -> Ptr a -> IO (ForeignPtr a) +newForeignPtrEnv finalizer env p + = do fObj <- newForeignPtr_ p + addForeignPtrFinalizerEnv finalizer env fObj + return fObj +#endif /* __HUGS__ */ #ifndef __GLASGOW_HASKELL__ mallocForeignPtr :: Storable a => IO (ForeignPtr a) mallocForeignPtr = do r <- malloc - newForeignPtr r finalizerFree + newForeignPtr finalizerFree r mallocForeignPtrBytes :: Int -> IO (ForeignPtr a) mallocForeignPtrBytes n = do r <- mallocBytes n - newForeignPtr r finalizerFree -#endif /* __HUGS__ || __NHC__ */ + newForeignPtr finalizerFree r +#endif /* !__GLASGOW_HASKELL__ */ +-- | This function is similar to 'Foreign.Marshal.Array.mallocArray', +-- but yields a memory area that has a finalizer attached that releases +-- the memory area. As with 'mallocForeignPtr', it is not guaranteed that +-- the block of memory was allocated by 'Foreign.Marshal.Alloc.malloc'. mallocForeignPtrArray :: Storable a => Int -> IO (ForeignPtr a) mallocForeignPtrArray = doMalloc undefined where - doMalloc :: Storable a => a -> Int -> IO (ForeignPtr a) + doMalloc :: Storable b => b -> Int -> IO (ForeignPtr b) doMalloc dummy size = mallocForeignPtrBytes (size * sizeOf dummy) +-- | This function is similar to 'Foreign.Marshal.Array.mallocArray0', +-- but yields a memory area that has a finalizer attached that releases +-- the memory area. As with 'mallocForeignPtr', it is not guaranteed that +-- the block of memory was allocated by 'Foreign.Marshal.Alloc.malloc'. mallocForeignPtrArray0 :: Storable a => Int -> IO (ForeignPtr a) mallocForeignPtrArray0 size = mallocForeignPtrArray (size + 1)