The Revenge of Finalizers
George Russell
ger at tzi.de
Thu Oct 17 10:51:04 EDT 2002
Simon Marlow wrote:
[snip]
>
> Ok, so it relies crucially on the fact that the 'if' causes evaluation.
> (you might have written it to be more lazy, so that the pair was
> returned immediately without evaluating contents1 first, for example).
>
> In that case, yes I agree it is horrible :)
[snip]
Flattery like that will get you nowhere. However in general I think
we can hide some of the horribleness from the user:
modify2IORefs :: IORef a -> IORef b -> (a -> b -> (a,b,c)) -> IO c
modify2IORefs ioRefA ioRefB updateFn =
do
res <- atomicModifyIORef ioRefA (\ a0 ->
unsafePerformIO (do
atomicModifyIORef ioRefB (\ b0 ->
let
(a1,b1,c) = updateFn a0 b0
in
a0 `seq` b0 `seq` (b1,(a1,c))
)
)
)
block (res `seq` return res)
Modulo whatever stupid type errors I have made, I think this should
provide a safe atomic update of two IORefs, except that you can
get non-termination should you set up circular dependencies.
However the latter problem (except that you will get deadlock) can occur
if you try to write
modify2MVars :: MVar a -> MVar b -> (a -> b -> (a,b,c)) -> IO c
and are I fear unsolvable, without a global lock.
I am not sure if all those seqs are necessary, but as Simon PJ would
say, my brain is hurting.
More information about the FFI
mailing list