X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=GHC%2FForeignPtr.hs;h=41bcfab96c2fb103905000c6aa06979a670339b2;hb=ea98be462413c2785386967865a511b3405bb031;hp=0069de2e93b6de65f9f625b58c2d1337c383d068;hpb=26021ff9493fb5bceba65415e8689e0d2a170d5e;p=ghc-base.git diff --git a/GHC/ForeignPtr.hs b/GHC/ForeignPtr.hs index 0069de2..41bcfab 100644 --- a/GHC/ForeignPtr.hs +++ b/GHC/ForeignPtr.hs @@ -26,6 +26,7 @@ module GHC.ForeignPtr castForeignPtr, newConcForeignPtr, addForeignPtrConcFinalizer, + finalizeForeignPtr ) where import Control.Monad ( sequence_ ) @@ -97,16 +98,16 @@ newConcForeignPtr p finalizer return fObj mallocForeignPtr :: Storable a => IO (ForeignPtr a) --- ^ allocates some memory and returns a ForeignPtr to it. The memory --- will be released automatically when the ForeignPtr is discarded. +-- ^ Allocate some memory and return a 'ForeignPtr' to it. The memory +-- will be released automatically when the 'ForeignPtr' is discarded. -- --- @mallocForeignPtr@ is equivalent to +-- 'mallocForeignPtr' is equivalent to -- --- > do { p <- malloc; newForeignPtr p free } +-- > do { p <- malloc; newForeignPtr finalizerFree p } -- --- although it may be implemented differently internally. You may not +-- although it may be implemented differently internally: you may not -- assume that the memory returned by 'mallocForeignPtr' has been --- allocated with C's @malloc()@. +-- allocated with 'Foreign.Marshal.Alloc.malloc'. mallocForeignPtr = doMalloc undefined where doMalloc :: Storable a => a -> IO (ForeignPtr a) doMalloc a = do @@ -117,8 +118,8 @@ mallocForeignPtr = doMalloc undefined } where (I# size) = sizeOf a --- | similar to 'mallocForeignPtr', except that the size of the memory required --- is given explicitly as a number of bytes. +-- | This function is similar to 'mallocForeignPtr', except that the +-- size of the memory required is given explicitly as a number of bytes. mallocForeignPtrBytes :: Int -> IO (ForeignPtr a) mallocForeignPtrBytes (I# size) = do r <- newIORef [] @@ -144,6 +145,12 @@ addForeignPtrConcFinalizer :: ForeignPtr a -> IO () -> IO () -- is an arbitrary @IO@ action. When it is invoked, the finalizer -- will run in a new thread. -- +-- NB. Be very careful with these finalizers. One common trap is that +-- if a finalizer references another finalized value, it does not +-- prevent that value from being finalized. In particular, 'Handle's +-- are finalized objects, so a finalizer should not refer to a 'Handle' +-- (including @stdout@, @stdin@ or @stderr@). +-- addForeignPtrConcFinalizer f@(ForeignPtr fo r) finalizer = do fs <- readIORef r writeIORef r (finalizer : fs) @@ -230,3 +237,15 @@ castForeignPtr :: ForeignPtr a -> ForeignPtr b -- ^This function casts a 'ForeignPtr' -- parameterised by one type into another type. castForeignPtr f = unsafeCoerce# f + +-- | Causes a the finalizers associated with a foreign pointer to be run +-- immediately. +finalizeForeignPtr :: ForeignPtr a -> IO () +finalizeForeignPtr foreignPtr = do + finalizers <- readIORef refFinalizers + sequence_ finalizers + writeIORef refFinalizers [] + where + refFinalizers = case foreignPtr of + (ForeignPtr _ ref) -> ref + (MallocPtr _ ref) -> ref