Proposal: add new forms of unsafePerformIO and unsafeInterleaveIO
duncan.coutts at worc.ox.ac.uk
Thu Feb 14 05:54:37 EST 2008
This proposal is to add two new variations on unsafePerformIO and one
new form of unsafeInterleaveIO to the System.IO.Unsafe module in the
base library (which already exports unsafePerformIO and
The additions are documented and portable to non-ghc.
Summary and documentation below, see patch attached to the ticket for
code details. http://hackage.haskell.org/trac/ghc/ticket/2095
Suggested timescale: ~2 weeks, ends Friday 29th February
* unsafeDupablePerformIO and unsafeDupableInterleaveIO When GHC
added SMP support the previous unsafePerform/InterleaveIO got
renamed to these two functions and new
unsafePerform/InterleaveIO functions were added that provide
protection against duplication in a multi-threaded context. This
protection comes at some cost so there are cases where it is ok
to uses these weaker forms if duplicating the IO action is safe.
These are already defined and documented in GHC.IOBase, this
patch just exports them.
* unsafeInlinePerformIO This is an even less safe form of
unsafePerformIO. It is used in the Data.ByteString
implementation and is very occasionally needed in other
projects. If it is needed it is better that it be supplied in a
portable form from a standard module with a sensible name and
with full documentation.
This version of 'unsafePerformIO' is slightly more efficient, because it
omits the check that the IO is only being performed by a single thread.
Hence, when you write 'unsafeDupablePerformIO', there is a possibility
that the IO action may be performed multiple times (on a
multiprocessor), and you should therefore ensure that it gives the same
results each time.
unsafeDupablePerformIO :: IO a -> a
TODO: Actually, unsafeDupableInterleaveIO is not yet documented,
that will have to be fixed.
unsafeDupableInterleaveIO :: IO a -> IO a
This variant of 'unsafePerformIO' is quite /mind-bogglingly unsafe/. It
unstitches the dependency chain that holds the IO monad together and
breaks all your ordinary intuitions about IO, sequencing and side
effects. Avoid it unless you really know what you are doing.
It is only safe for operations which are genuinely pure (not just
externally pure) for example reading from an immutable foreign data
structure. In particular, you should do no memory allocation inside an
'unsafeInlinePerformIO' block. This is because an allocation is a
constant and is likely to be floated out and shared. More generally, any
part of any IO action that does not depend on a function argument is
likely to be floated to the top level and have its result shared.
It is more efficient because in addition to the checks that
'unsafeDupablePerformIO' omits, we also inline. Additionally we do not
pretend that the body is lazy which allows the strictness analyser to
see the strictness in the body. In turn this allows some re-ordering of
operations and any corresponding side-effects.
With GHC it compiles to essentially no code and it exposes the body to
unsafeInlinePerformIO :: IO a -> a
More information about the Libraries