X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=GHC%2FIOBase.lhs;h=60ae45b0a28f304a641b0257f324f440c6821d0e;hb=3aca3f915d2edc71a8633181577258f04996e42a;hp=5f84206c4584f6fbdbe86d5e86989dacc4a1c46f;hpb=9c33481176d370dfe9b03ea1a0b803227cc1df7f;p=ghc-base.git 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]