The Revenge of Finalizers

Simon Marlow simonmar at microsoft.com
Thu Oct 17 10:13:42 EDT 2002


> simpleToggle2 :: IORef Bool -> IORef Bool -> IO (Just (Bool,Bool))
> 
> which attempts to flip the two IORefs from True to False (if 
> they are both True);
> otherwise returning their actual values.  Then you could code 
> this something like this
> (no I'm not going to check if it passes GHC)
> 
> simpleToggle2 ioRef1 ioRef2 =
>    do
>       res <- atomicModifyIORef ioRef1 (\ contents1 ->
>          unsafePerformIO (atomicModifyIORef ioRef2 (\ contents2 ->
>             if contents1 && contents2 
>                then
>                  (False,(False,Nothing))
>                else
>                  (contents2,(contents1,Just (contents1,contents2)))
>             )
>          )
>       seq res (return res)
> 
> Then the first atomicModifyIORef replaces the contents of 
> ioRef1 by a thunk, and
> returns another thunk.  The seq then proceeds to evaluate 
> this thunk, causing
> the unsafePerformIO to be run, which changes ioRef2.
> 
> There IS a potential problem, because if you run 
> simpleToggle2 on the same ioRef
> 
> simpleToggle2 ioRef ioRef
> 
> or if two threads run simpleToggle2 simultaneously on the 
> same ioRefs but in opposite order
> 
> simpleToggle2 ioRef1 ioRef2 || simpleToggle2 ioRef2 ioRef1

Don't you run into a problem even if the two threads use the same
ordering?  Suppose

  - thread 1 does the atomicModifyIORef, and gets preempted before
    doing the seq
  - thread 2 does its own atomicModifyIORef, and the seq.  Thread 2
    gets an inconsistent view of the IORefs.

right?

Simon



More information about the FFI mailing list