From: simonpj Date: Wed, 11 Sep 2002 11:06:05 +0000 (+0000) Subject: [project @ 2002-09-11 11:06:05 by simonpj] X-Git-Tag: nhc98-1-18-release~857 X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=3aca3f915d2edc71a8633181577258f04996e42a;hp=9c33481176d370dfe9b03ea1a0b803227cc1df7f;p=ghc-base.git [project @ 2002-09-11 11:06:05 by simonpj] Add documentation about unsafePerformIO --- diff --git a/GHC/IOBase.lhs b/GHC/IOBase.lhs index 5f84206..60ae45b 100644 --- a/GHC/IOBase.lhs +++ b/GHC/IOBase.lhs @@ -131,9 +131,31 @@ free of side effects and independent of its environment. If the I\/O computation wrapped in 'unsafePerformIO' performs side effects, then the relative order in which those side effects take place (relative to the main I\/O trunk, or other calls to -'unsafePerformIO') is indeterminate. - -However, it is less well known that +'unsafePerformIO') is indeterminate. You have to be careful when +writing and compiling modules that use 'unsafePerformIO': + * Use @{-# NOINLINE foo #-}@ as a pragma on any function @foo@ + that calls 'unsafePerformIO'. If the call is inlined, + the I/O may be performed more than once. + + * Use the compiler flag @-fno-cse@ to prevent common sub-expression + elimination being performed on the module, which might combine + two side effects that were meant to be separate. A good example + is using multiple global variables (like @test@ in the example below). + + * Make sure that the either you switch off let-floating, or that the + call to 'unsafePerformIO' cannot float outside a lambda. For example, + if you say: + @ + f x = unsafePerformIO (newIORef []) + @ + you may get only one reference cell shared between all calls to @f@. + Better would be + @ + f x = unsafePerformIO (newIORef [x]) + @ + because now it can't float outside the lambda. + +It is less well known that 'unsafePerformIO' is not type safe. For example: > test :: IORef [a]