[reactive] unsafePerformIO: is it correctly used?

Peter Verswyvelen bugfact at gmail.com
Fri Nov 21 09:56:29 EST 2008


Okay. But there are a couple of other functions that use unsafePerformIO.
Are all of these behaving nicely then? Just double checking :)
On Fri, Nov 21, 2008 at 8:22 AM, Conal Elliott <conal at conal.net> wrote:

> Hi Peter,
>
> I'm glad to see you're getting into the Reactive code!
>
> As a complement to Luke's answer:
>
> I think readIVar is an exception to the usual guidelines below.  The point
> of the IVar type is that it can get written *at most once*, so any read
> will yield the same value.  It doesn't matter in this case whether the
> readMVar computation is duplicated.  It always has to yield the same result,
> namely the only value that has been or will be written to the MVar, or
> bottom if no value ever gets written.  As Luke mentioned, the IVar interface
> does not allow takeMVar to be called, except via readMVar, which replaces
> the value after reading.
>
>   - Conal
>
> 2008/11/20 Peter Verswyvelen <bugfact at gmail.com>
>
>> When I was browsing the GHC documentation, I came across the following:
>>
>> 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.
>> 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.
>>
>> Now in Reactive, in e.g. the internal IVar.hs module, I see
>>
>> readIVar :: IVar a -> a
>> readIVar (IVar v) = unsafePerformIO $ readMVar v
>>
>> At first sight this function is not following all the rules described
>> above. Could this cause problems?
>>
>> Cheers,
>> Peter
>>
>>
>>
>>
>> _______________________________________________
>> Reactive mailing list
>> Reactive at haskell.org
>> http://www.haskell.org/mailman/listinfo/reactive
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/reactive/attachments/20081121/dd6d358a/attachment.htm


More information about the Reactive mailing list