Use of evaluate in Control.Concurrent.MVar

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Use of evaluate in Control.Concurrent.MVar

David Feuer
Control.Concurrent.MVar uses `evaluate` in a couple places, and I
don't understand why:

modifyMVar :: MVar a -> (a -> IO (a,b)) -> IO b
modifyMVar m io =
  mask $ \restore -> do
    a      <- takeMVar m
    (a',b) <- restore (io a >>= evaluate) `onException` putMVar m a
    putMVar m a'
    return b

modifyMVarMasked :: MVar a -> (a -> IO (a,b)) -> IO b
modifyMVarMasked m io =
  mask_ $ do
    a      <- takeMVar m
    (a',b) <- (io a >>= evaluate) `onException` putMVar m a
    putMVar m a'
    return b

The general purpose is to make sure that the result of the IO action
is forced to head normal form within the scope of the `catch` block
created by `onException`. But in this context, I don't see why we need
to use `evaluate` rather than just `seq`, or why that is desirable.
Couldn't we just do this?

modifyMVar m io =
  mask $ \restore -> do
    a      <- takeMVar m
    (a',b) <- restore (io a >>= (pure $!)) `onException` putMVar m a
    putMVar m a'
    return b

David
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Use of evaluate in Control.Concurrent.MVar

Roman Cheplyaka-2
Hi David,

On 12/10/2020 21.01, David Feuer wrote:
> Couldn't we just do this?
>
> modifyMVar m io =
>   mask $ \restore -> do
>     a      <- takeMVar m
>     (a',b) <- restore (io a >>= (pure $!)) `onException` putMVar m a
>     putMVar m a'
>     return b

No — the haddocks for 'evaluate' in Control.Exception explain the difference between the two. In particular,

> The rule of thumb is to use evaluate to force or handle exceptions in lazy values. If, on the other hand, you are forcing a lazy value for efficiency reasons only and do not care about exceptions, you may use return $! x.

If you want to know why, I think you can find some old bugs in the ghc bug tracker that resulted from an incorrect usage of return $! ... where evaluate was warranted.

Roman
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Use of evaluate in Control.Concurrent.MVar

David Feuer
Yes, I generally understand that; I just don't *think* it applies
here. The issue with `seq` tends to be that strictness information can
propagate "back in time", or forcing can be delayed, etc. I just don't
immediately see that as an issue in this *particular* spot. That said,
I imagine that in many cases the compiler will see that the pair is
surely produced, in which case the `evaluate` will go away.

On Mon, Oct 12, 2020 at 2:20 PM Roman Cheplyaka <[hidden email]> wrote:

>
> Hi David,
>
> On 12/10/2020 21.01, David Feuer wrote:
> > Couldn't we just do this?
> >
> > modifyMVar m io =
> >   mask $ \restore -> do
> >     a      <- takeMVar m
> >     (a',b) <- restore (io a >>= (pure $!)) `onException` putMVar m a
> >     putMVar m a'
> >     return b
>
> No — the haddocks for 'evaluate' in Control.Exception explain the difference between the two. In particular,
>
> > The rule of thumb is to use evaluate to force or handle exceptions in lazy values. If, on the other hand, you are forcing a lazy value for efficiency reasons only and do not care about exceptions, you may use return $! x.
>
> If you want to know why, I think you can find some old bugs in the ghc bug tracker that resulted from an incorrect usage of return $! ... where evaluate was warranted.
>
> Roman
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries