<div dir="ltr"><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><p class="MsoNormal" style="margin:0cm 0cm 8pt;line-height:107%;font-size:11pt;font-family:Calibri,sans-serif"><span lang="EN-US">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.
Your may find discussion here <a href="https://github.com/typelevel/cats-effect/issues/451" style="color:rgb(5,99,193)">https://github.com/typelevel/cats-effect/issues/451</a>
and event try to advocate, tl;dr. Anyway, what is so wrong with MVar?</span></p>

<p class="gmail-MsoListParagraphCxSpFirst" style="margin:0cm 0cm 0.0001pt 36pt;line-height:107%;font-size:11pt;font-family:Calibri,sans-serif"><span lang="EN-US">1.<span style="font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:7pt;line-height:normal;font-family:"Times New Roman"">       </span></span><span lang="EN-US">It’s complex. Each MVar has 2 state
transitions, each may block. </span></p>

<p class="gmail-MsoListParagraphCxSpLast" style="margin:0cm 0cm 8pt 36pt;line-height:107%;font-size:11pt;font-family:Calibri,sans-serif"><span lang="EN-US">2.<span style="font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:7pt;line-height:normal;font-family:"Times New Roman"">       </span></span><span lang="EN-US">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`) this force programmer to
mask asynchronous exceptions during the MVar acquisition and since `take`
function may block, this will delay task cancelation. Well, you may argue what
the `takeMVar` function is actually interruptible, but I’m going to show an easier
approach which renders interpretability magic unnecessary.</span></p>

<p class="MsoNormal" style="margin:0cm 0cm 8pt;line-height:107%;font-size:11pt;font-family:Calibri,sans-serif"><span lang="EN-US">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 <a href="https://github.com/ovotech/fs2-kafka/blob/master/src/main/scala/fs2/kafka/internal/Synchronized.scala" style="color:rgb(5,99,193)">https://github.com/ovotech/fs2-kafka/blob/master/src/main/scala/fs2/kafka/internal/Synchronized.scala</a>
(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). </span></p>

<p class="MsoNormal" style="margin:0cm 0cm 8pt;line-height:107%;font-size:11pt;font-family:Calibri,sans-serif"><span lang="EN-US">For people
who don’t read Scala, the approach is fairly simple. Each thread which want to touch
mutex, will create IVar, atomically swap it in the IORef masked (note, that IORef’s
operations non-blocking), unmask and wait for previous become available IVar *unmasked*.
Then it will either perform it’s operations or fail due to the interruption or
exception and trigger newly installed IVar anyway. It just works. Without any «interruptible»
magic.</span></p>

<p class="MsoNormal" style="margin:0cm 0cm 8pt;line-height:107%;font-size:11pt;font-family:Calibri,sans-serif"><span lang="EN-US">So, which
benefits can we get?</span></p>

<p class="gmail-MsoListParagraphCxSpFirst" style="margin:0cm 0cm 0.0001pt 36pt;line-height:107%;font-size:11pt;font-family:Calibri,sans-serif"><span lang="EN-US">1.<span style="font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:7pt;line-height:normal;font-family:"Times New Roman"">       </span></span><span lang="EN-US">Simpler implementation of basic
primitives. Obliviously IORef is fairly simple. IVar is also mind be simpler
than MVar, and possibly faster (just “possibly”, I don’t know how it’s implemented,
but I guess lesser state transitions implies less logic).</span></p>

<p class="gmail-MsoListParagraphCxSpMiddle" style="margin:0cm 0cm 0.0001pt 36pt;line-height:107%;font-size:11pt;font-family:Calibri,sans-serif"><span lang="EN-US">2.<span style="font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:7pt;line-height:normal;font-family:"Times New Roman"">       </span></span><span lang="EN-US">Simplified deadlock analysis. Really,
we have only IVar with only one state transition and only one potentially
blocking operation.</span></p>

<p class="gmail-MsoListParagraphCxSpLast" style="margin:0cm 0cm 8pt 36pt;line-height:107%;font-size:11pt;font-family:Calibri,sans-serif"><span lang="EN-US">3.<span style="font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:7pt;line-height:normal;font-family:"Times New Roman"">       </span></span><span lang="EN-US">Magicless support of interruptions.
We don’t need to separate mask/uninterruptibleMask anymore, because all updates
are non-blocking, and all waits are unmasked. </span></p></div></div></div>