summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2020-04-19 11:27:49 -0400
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-02-14 03:35:07 -0500
commita699389f9f2c955b14b777b0336f966b57070982 (patch)
tree75cc30b0f412135671f43c8cb975340acfc10fd2
parent5e71dd3379ec4738c3f88271803d0de9b77e004f (diff)
downloadhaskell-a699389f9f2c955b14b777b0336f966b57070982.tar.gz
base: Add unsafeWithForeignPtr
-rw-r--r--libraries/base/Foreign/ForeignPtr/Imp.hs25
-rw-r--r--libraries/base/GHC/ForeignPtr.hs39
2 files changed, 38 insertions, 26 deletions
diff --git a/libraries/base/Foreign/ForeignPtr/Imp.hs b/libraries/base/Foreign/ForeignPtr/Imp.hs
index 2fc18689a9..3af5da13a9 100644
--- a/libraries/base/Foreign/ForeignPtr/Imp.hs
+++ b/libraries/base/Foreign/ForeignPtr/Imp.hs
@@ -66,31 +66,6 @@ newForeignPtr finalizer 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
--- 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 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
--- 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 (unsafeForeignPtrToPtr fo)
- touchForeignPtr fo
- return r
-
-- | 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
diff --git a/libraries/base/GHC/ForeignPtr.hs b/libraries/base/GHC/ForeignPtr.hs
index a64d4d19c6..6cc55221f4 100644
--- a/libraries/base/GHC/ForeignPtr.hs
+++ b/libraries/base/GHC/ForeignPtr.hs
@@ -45,8 +45,11 @@ module GHC.ForeignPtr
unsafeForeignPtrToPtr,
castForeignPtr,
plusForeignPtr,
- -- * Finalization
+ -- * Control over lifetype
+ withForeignPtr,
+ unsafeWithForeignPtr,
touchForeignPtr,
+ -- * Finalization
finalizeForeignPtr
-- * Commentary
-- $commentary
@@ -503,6 +506,40 @@ newForeignPtr_ (Ptr obj) = do
r <- newIORef NoFinalizers
return (ForeignPtr obj (PlainForeignPtr r))
+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 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
+-- 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 = unsafeWithForeignPtr
+
+-- | This is similar to 'withForeignPtr' but comes with an important caveat:
+-- the user must guarantee that the continuation does not diverge (e.g. loop or
+-- throw an exception). In exchange for this loss of generality, this function
+-- offers the ability of GHC to optimise more aggressively.
+--
+-- See issue #17760 for the motivation for this function.
+unsafeWithForeignPtr :: ForeignPtr a -> (Ptr a -> IO b) -> IO b
+unsafeWithForeignPtr fo f = do
+ r <- f (unsafeForeignPtrToPtr fo)
+ touchForeignPtr fo
+ return r
+
touchForeignPtr :: ForeignPtr a -> IO ()
-- ^This function ensures that the foreign object in
-- question is alive at the given place in the sequence of IO