[Haskell-cafe] MVar considered harmful

Alexandru Nedelcu groups7 at alexn.org
Wed Jan 2 00:44:25 UTC 2019


I’m the author of the `MVar` implementation in Cats-Effect.

> Recently I had an interesting discussion on MVars with cats-effect 
> library
> designers. Cats-effect brings MVar synchronization primitive along 
> with
> other IO stuff to the Scala programming language. I tried to persuade 
> them
> to include some Control.Concurrent.MVar’s functions to  the library 
> but has
> failed completely. Moreover, now I think that MVar is a poor choice 
> for
> basic synchronization primitive.

I believe `MVar` is a superb choice for synchronisation, because it 
behaves like a blocking queue, which in computer science is a pretty 
fundamental tool.

It is true that in Cats-Effect an `MVar` might not be a primitive, but 
as I explained in that thread, on top of the JVM the real primitives are 
the low level building blocks like `AtomicReference`.

> 1. It’s complex. Each MVar has 2 state transitions, each may block.

Blocking is a feature. If you have to build that logic via `Ref` 
(`IORef`), you’d have to model the state machine by yourself and 
that’s complexity being pushed to the user.

> 2. It does not play well in presence of asynchronous exceptions. More
> specifically, `take` and `put` operations should be balanced (each 
> `take`
> must be followed by `put`)

The `take` followed by a `put` rule is only for your “modify” 

The problem is that a `modify` function that’s described via `take` + 
`put` is not an atomic operation and this is a problem, but only if any 
of the actors accessing the `MVar` are doing so in a different order.

This isn’t a problem for other use-cases tough.

> this force programmer to mask asynchronous
> exceptions during the MVar acquisition and since `take` function may 
> block,
> this will delay task cancelation.

I don’t have much experience with Haskell’s async exceptions, but if 
you mean that `take` must be executed as `uncancelable`, via `bracket`, 
then this is a problem that we can fix in Cats-Effect 2.x, as mentioned 
in that thread.

> What could be the sensible alternative? Guy from the cats-effect 
> suggested
> me IVar + atomic reference (IORef). This pattern separates concern of
> blocking (synchronization) from the atomic mutation. So everything can 
> be
> represented as atomic reference with IVar inside. Just look at this
> beautiful mutex implementation
> https://github.com/ovotech/fs2-kafka/blob/master/src/main/scala/fs2/kafka/internal/Synchronized.scala

As I said above, most things on top of the JVM can be implemented via an 
`AtomicReference` due to its memory model and this is no exception.

But it’s not elegant, or simple ;-)

> (By ”beautiful” I mean approach itself of course, but not the 
> Scala’s
> syntax. Scala is one of most ugliest girls after C++ I was forced to 
> date
> with by my employer for money. Thankfully he didn’t force me to do 
> the same
> things with her grandma Java).

That’s unnecessary and TBH a turnoff.


Alexandru Nedelcu
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20190102/28036ba9/attachment.html>

More information about the Haskell-Cafe mailing list