unix
unix copied to clipboard
Use unsafeDupablePerformIO instead of unsafePerformIO in struct field reads?
As it unsafePerformIO is much slower and forces the program to run single-threadedly while providing no benefits.
Can you point at a few salient examples?
As it unsafePerformIO is much slower and forces the program to run single-threadedly while providing no benefits.
It does provide benefits. bracketed functions inside unsafeDupablePerformIO are broken: https://hackage.haskell.org/package/base-4.16.2.0/docs/System-IO-Unsafe.html#v:unsafeDupablePerformIO
So we'd need to know exactly what you mean to judge whether that's a good idea.
https://github.com/haskell/unix/blob/b315336f219c9afdf1586bb21c90ee76f59271d1/System/Posix/Files/Common.hsc all of these for example
Indeed those particular examples are IIRC safe for unsafeDupablePerformIO or even something more aggressive, like similar read-only code in bytestring via accursedUnutterablePerformIO:
{-# INLINE accursedUnutterablePerformIO #-}
accursedUnutterablePerformIO :: IO a -> a
accursedUnutterablePerformIO (IO m) = case m realWorld# of (# _, r #) -> r
The difference with unsafeDupablePerformIO is:
unsafeDupablePerformIO (IO m) = case runRW# m of (# _, a #) -> lazy a
Which takes a few extra precautions against some compiler optimisations, but ultimately (late) inlines to similar code. My sense is that if the bytestring code can read foreign pointer payloads with accursedUnutterablePerformIO, the same should be true here. For example in ByteString.head, we have: accursedUnutterablePerformIO $ unsafeWithForeignPtr x $ \p -> peek p. Which by the way also uses unsafeWithForeignPtr.