<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>barrucadu&#39;s memos - Research (Deja Fu / CoCo)</title>
  <link href="https://memo.barrucadu.co.uk/taxon/research-dejafucoco.xml" rel="self" />
  <link href="https://memo.barrucadu.co.uk/" />
  <id>https://memo.barrucadu.co.uk/taxon/research-dejafucoco.xml</id>
  <author>
    <name>Michael Walker</name>
    <email>mike@barrucadu.co.uk</email>
  </author>
  
  <updated>2021-05-30T00:00:00Z</updated>
  
  
  <entry>
    <title>It&#39;s not a no-op to unmask an interruptible operation (and dejafu detects this)</title>
    <link href="https://memo.barrucadu.co.uk/restore-interruptible.html" />
    <id>https://memo.barrucadu.co.uk/restore-interruptible.html</id>
    <published>2021-05-30T00:00:00Z</published>
    <updated>2021-05-30T00:00:00Z</updated>
    <summary type="html">
      <![CDATA[
<p>User effectfully on reddit wrote an article <a href="https://github.com/effectfully-ou/sketches/tree/master/restore-interruptible">It’s not a no-op to unmask an interruptible operation</a> (<a href="https://old.reddit.com/r/haskell/comments/nntfui/its_not_a_noop_to_unmask_an_interruptible/">reddit discussion</a>) about a small gotcha with interruptible operations and asynchronous exceptions.</p>
<p>The gist of it is that this snippet of code:</p>
<pre class="haskell"><code>mask $ \restore -&gt; do
  putMVar var x
  ...</code></pre>
<p>behaves differently to this snippet of code:</p>
<pre class="haskell"><code>mask $ \restore -&gt; do
  restore $ putMVar var x
  ...</code></pre>
<p>in the presence of asynchronous exceptions. The post goes on to explain what the different behaviours are and why they crop up; but thinking about concurrency is too much like effort, let’s turn to <a href="http://hackage.haskell.org/package/dejafu">dejafu</a>!</p>
<h2 id="no-restore-around-the-put">No restore around the put</h2>
<p>In this test case, I want to see</p>
<ol type="1">
<li>if the <code>putMVar var x</code> is interrupted by an asynchronous exception; and</li>
<li>if the <code>...</code> bit of code gets executed</li>
</ol>
<p>So the actual test case is a bit more complex than just the snippet above. We’re going to need three threads:</p>
<pre class="haskell"><code>thread1 = mask $ \restore -&gt; catch
  (putMVar var &quot;hello world&quot; &gt;&gt; putMVar success True)
  (\(_ :: SomeException) -&gt; putMVar success False)

thread2 = putMVar var &quot;interrupted!&quot;

thread3 = killThread thread1</code></pre>
<p>Putting it together into an actual test case, we get:</p>
<pre class="haskell"><code>import Control.Concurrent.Classy
import Control.Exception (SomeException)

example1 :: MonadConc m =&gt; m (String, Bool)
example1 = do
  var &lt;- newEmptyMVar
  success &lt;- newEmptyMVar
  interruptMe &lt;- newEmptyMVar

  tid &lt;- fork $ mask $ \_ -&gt; do
    putMVar interruptMe ()
    catch
      (putMVar var &quot;hello world&quot; &gt;&gt; putMVar success True)
      (\(_ :: SomeException) -&gt; putMVar success False)

  -- wait for the thread to be inside the `mask`, then fork a thread
  -- to race on the `putMVar` and also throw an async exception.
  takeMVar interruptMe
  _ &lt;- fork $ putMVar var &quot;interrupted!&quot;
  killThread tid

  (,) &lt;$&gt; readMVar var &lt;*&gt; readMVar success</code></pre>
<p>There’s a little extra ceremony involved in making sure that the race happens <em>after</em> the <code>mask</code>—we need a new <code>interruptMe</code> <code>MVar</code>—but other than that it’s fairly straightforward.</p>
<p>dejafu finds two behaviours for this example, and gives abbreviated execution traces:</p>
<pre><code>&gt; autocheck example1
[pass] Successful
[fail] Deterministic
    (&quot;hello world&quot;,True) S0-----S1--------S0------

    (&quot;interrupted!&quot;,False) S0-----S1---P0---S2--S1-S0---S1---S0--
False</code></pre>
<h2 id="do-restore-around-the-put">Do restore around the put</h2>
<p>Here’s our new test case:</p>
<pre class="haskell"><code>import Control.Concurrent.Classy
import Control.Exception (SomeException)

example2 :: MonadConc m =&gt; m (String, Bool)
example2 = do
  interruptMe &lt;- newEmptyMVar
  var &lt;- newEmptyMVar
  success &lt;- newEmptyMVar

  tid &lt;- fork $ mask $ \restore -&gt; do
    putMVar interruptMe ()
    catch
      (restore (putMVar var &quot;hello world&quot;) &gt;&gt; putMVar success True)
      (\(_ :: SomeException) -&gt; putMVar success False)

  -- wait for the thread to be inside the `mask`, then fork a thread
  -- to race on the `putMVar` and also throw an async exception.
  takeMVar interruptMe
  _ &lt;- fork $ putMVar var &quot;interrupted!&quot;
  killThread tid

  (,) &lt;$&gt; readMVar var &lt;*&gt; readMVar success</code></pre>
<p>Lo and behold, dejafu finds a <em>third</em> behaviour:</p>
<pre><code>&gt; autocheck example2
[pass] Successful
[fail] Deterministic
    (&quot;hello world&quot;,True) S0-----S1-----------S0------

    (&quot;hello world&quot;,False) S0-----S1-----P0-----S1---S0--

    (&quot;interrupted!&quot;,False) S0-----S1----P0----S1---S2--S0---
False</code></pre>
<p>So it seems that we can now end up in the situation where the <code>putMVar var "hello world"</code> does happen, but <em>after</em> writing to the <code>MVar</code> the asynchronous exception is delivered and so we hit the <code>putMVar success False</code> case.</p>
<p>Weird, right?</p>
<h2 id="whats-the-difference">What’s the difference?</h2>
<p>We can get the actual execution trace for the new case with a lower-level function in dejafu, <code>runSCT</code>. Digging through it, we can find the pre-emption of thread 1 (the first thread forked) by thread 0 (the main thread):</p>
<pre class="haskell"><code>(SwitchTo main, [(1, WillResetMasking True MaskedInterruptible)], TakeMVar 1 [])</code></pre>
<p>This says that we switched to the main thread, and it performed a <code>takeMVar</code> operation. And furthermore, that thread 1 <em>will next</em> reset the masking state back to <code>MaskedInterruptible</code>.</p>
<p>Now the issue becomes clear. The problematic snippet:</p>
<pre class="haskell"><code>mask $ \restore -&gt; do
  restore $ putMVar var x
  ...</code></pre>
<p>Actually means to perform these steps:</p>
<ol type="1">
<li>Change the masking state to <code>MaskedInterruptible</code></li>
<li>Change the masking state to <code>Unmasked</code></li>
<li>Do <code>putMVar var x</code></li>
<li>Reset the masking state back to <code>MaskedInterruptible</code></li>
<li>Do <code>...</code></li>
</ol>
<p>The issue is that completing the <code>putMVar var x</code> call and resetting the masking state are <em>two</em> operations. That’s not atomic. So there is a chance that an exception can be delivered between them.</p>
<p>And that’s the issue explained in <a href="https://github.com/effectfully-ou/sketches/tree/master/restore-interruptible">It’s not a no-op to unmask an interruptible operation</a>, replicated with dejafu.</p>

      ]]>
    </summary>
  </entry>
  
  <entry>
    <title>dejafu-2.0.0.0</title>
    <link href="https://memo.barrucadu.co.uk/dejafu-2.0.0.0.html" />
    <id>https://memo.barrucadu.co.uk/dejafu-2.0.0.0.html</id>
    <published>2019-02-12T00:00:00Z</published>
    <updated>2019-02-12T00:00:00Z</updated>
    <summary type="html">
      <![CDATA[
<p>(this message has also been sent to <a href="https://www.reddit.com/r/haskell/comments/aq09u5/ann_dejafu2000_a_library_for_unittesting/">/r/haskell</a> and <a href="https://mail.haskell.org/pipermail/haskell-cafe/2019-February/130694.html">haskell-cafe</a>)</p>
<hr />
<p>I’m pleased to announce a new super-major release of <a href="http://hackage.haskell.org/package/dejafu">dejafu</a>, a library for testing concurrent Haskell programs.</p>
<p>While there are breaking changes, common use-cases shouldn’t be affected too significantly (or not at all). There is a brief guide to the changes, and how to migrate if necessary, <a href="https://dejafu.readthedocs.io/en/latest/migration_1x_2x.html">on the website</a>.</p>
<h2 id="whats-dejafu">What’s dejafu?</h2>
<p>dejafu is a unit-testing library for concurrent Haskell programs. Tests are deterministic, and work by systematically exploring the possible schedules of your concurrency-using test case, allowing you to confidently check your threaded code.</p>
<p><a href="http://hackage.haskell.org/package/hunit-dejafu">HUnit</a> and <a href="http://hackage.haskell.org/package/tasty-dejafu">Tasty</a> bindings are available.</p>
<p>dejafu requires your test case to be written against the <code>MonadConc</code> typeclass from the <a href="http://hackage.haskell.org/package/concurrency">concurrency</a> package. This is a necessity, dejafu cannot peek inside your <code>IO</code> or <code>STM</code> actions, so it needs to be able to plug in an alternative implementation of the concurrency primitives for testing. There is some guidance for how to switch from <code>IO</code> code to <code>MonadConc</code> code <a href="https://dejafu.readthedocs.io/en/latest/typeclass.html">on the website</a>.</p>
<p>If you really need <code>IO</code>, you can use <code>MonadIO</code> - but make sure it’s deterministic enough to not invalidate your tests!</p>
<p>Here’s a small example reproducing a deadlock found in an earlier version of the <a href="http://hackage.haskell.org/package/auto-update">auto-update</a> library:</p>
<pre><code>&gt; :{
autocheck $ do
  auto &lt;- mkAutoUpdate defaultUpdateSettings
  auto
:}
[fail] Successful
    [deadlock] S0--------S1-----------S0-
[fail] Deterministic
    [deadlock] S0--------S1-----------S0-

    () S0--------S1--------p0--</code></pre>
<p>dejafu finds the deadlock, and gives a simplified execution trace for each distinct result. More in-depth traces showing exactly what each thread did are also available. This is using a version of auto-update modified to use the <code>MonadConc</code> typeclass. The source is in the <a href="https://github.com/barrucadu/dejafu/blob/master/dejafu-tests/lib/Examples/AutoUpdate.hs">dejafu testsuite</a>.</p>
<h2 id="whats-new">What’s new?</h2>
<p>The highlights for this release are setup actions, teardown actions, and invariants:</p>
<ul>
<li><p><strong>Setup actions</strong> are for things which are not really a part of your test case, but which are needed for it (for example, setting up a test distributed system). As dejafu can run a single test case many times, repeating this work can be a significant overhead. By defining this as a setup action, dejafu can “snapshot” the state at the end of the action, and efficiently reload it in subsequent executions of the same test.</p></li>
<li><p><strong>Teardown actions</strong> are for things you want to run after your test case completes, in all cases, even if the test deadlocks (for example). As dejafu controls the concurrent execution of the test case, inspecting shared state is possible even if the test case fails to complete.</p></li>
<li><p><strong>Invariants</strong> are effect-free atomically-checked conditions over shared state which must always hold. If an invariant throws an exception, the test case is aborted, and any teardown action run.</p></li>
</ul>
<p>Here is an example of a setup action with an invariant:</p>
<pre><code>&gt; :{
autocheck $
  let setup = do
        var &lt;- newEmptyMVar
        registerInvariant $ do
          value &lt;- inspectMVar var
          when (value == Just 1) $
            throwM Overflow
        pure var
  in withSetup setup $ \var -&gt; do
       fork $ putMVar var 0
       fork $ putMVar var 1
       tryReadMVar var
:}
[fail] Successful
    [invariant failure] S0--P2-
[fail] Deterministic
    [invariant failure] S0--P2-

    Nothing S0----

    Just 0 S0--P1--S0--</code></pre>
<p>In the <code>[invariant failure]</code> case, thread 2 is scheduled, writing the forbidden value “1” to the MVar, which terminates the test.</p>
<p>Here is an example of a setup action with a teardown action:</p>
<pre><code>&gt; :{
autocheck $
  let setup = newMVar ()
      teardown var (Right _) = show &lt;$&gt; tryReadMVar var
      teardown _   (Left  e) = pure (show e)
  in withSetupAndTeardown setup teardown $ \var -&gt; do
       fork $ takeMVar var
       takeMVar var
:}
[pass] Successful
[fail] Deterministic
    &quot;Nothing&quot; S0---

    &quot;Deadlock&quot; S0-P1--S0-</code></pre>
<p>The teardown action can perform arbitrary concurrency effects, including inspecting any mutable state returned by the setup action.</p>
<p>Setup and teardown actions were previously available in a slightly different form as the <code>dontCheck</code> and <code>subconcurrency</code> functions, which have been removed (see the migration guide if you used these).</p>

      ]]>
    </summary>
  </entry>
  
  <entry>
    <title>Simplifying Execution Traces</title>
    <link href="https://memo.barrucadu.co.uk/simplifying-execution-traces.html" />
    <id>https://memo.barrucadu.co.uk/simplifying-execution-traces.html</id>
    <published>2018-03-08T00:00:00Z</published>
    <updated>2018-03-08T00:00:00Z</updated>
    <summary type="html">
      <![CDATA[
<p>It’s well known that randomly generated test failures are a poor debugging aid. That’s why every non-toy randomised property testing library (like <a href="http://hackage.haskell.org/package/hedgehog">Hedgehog</a> or <a href="https://github.com/HypothesisWorks/hypothesis-python">Hypothesis</a> or <a href="http://hackage.haskell.org/package/QuickCheck">QuickCheck</a>) puts a considerable amount of effort into shrinking failures. It’s a non-trivial problem, but it’s absolutely essential.</p>
<p>It’s also something that dejafu does not do.</p>
<h2 id="running-example">Running example</h2>
<p>I’m going to use the “stores are transitively visible” litmus test as a running example. Here it is:</p>
<pre class="haskell"><code>import qualified Control.Monad.Conc.Class as C
import           Test.DejaFu.Internal
import           Test.DejaFu.SCT
import           Test.DejaFu.SCT.Internal.DPOR
import           Test.DejaFu.Types
import           Test.DejaFu.Utils

storesAreTransitivelyVisible :: C.MonadConc m =&gt; m (Int, Int, Int)
storesAreTransitivelyVisible = do
  x &lt;- C.newCRef 0
  y &lt;- C.newCRef 0
  j1 &lt;- C.spawn (C.writeCRef x 1)
  j2 &lt;- C.spawn (do r1 &lt;- C.readCRef x; C.writeCRef x 1; pure r1)
  j3 &lt;- C.spawn (do r2 &lt;- C.readCRef y; r3 &lt;- C.readCRef x; pure (r2,r3))
  (\() r1 (r2,r3) -&gt; (r1,r2,r3)) &lt;$&gt; C.readMVar j1 &lt;*&gt; C.readMVar j2 &lt;*&gt; C.readMVar j3</code></pre>
<p>I picked this one because it’s kind of arbitrarily complex. It’s a small test, but it’s for the relaxed memory implementation, so there’s a lot going on. It’s a fairly dense test.</p>
<p>I’m now going to define a metric of trace complexity which I’ll justify in a moment:</p>
<pre class="haskell"><code>complexity :: Trace -&gt; (Int, Int, Int, Int)
complexity = foldr go (0,0,0,0) where
  go (SwitchTo _, _, CommitCRef _ _) (w, x, y, z) = (w+1, x+1, y,   z)
  go (Start    _, _, CommitCRef _ _) (w, x, y, z) = (w+1, x,   y+1, z)
  go (Continue,   _, CommitCRef _ _) (w, x, y, z) = (w+1, x,   y,   z+1)
  go (SwitchTo _, _, _)              (w, x, y, z) = (w,   x+1, y,   z)
  go (Start    _, _, _)              (w, x, y, z) = (w,   x,   y+1, z)
  go (Continue,   _, _)              (w, x, y, z) = (w,   x,   y,   z+1)</code></pre>
<p>Using the <code>183-shrinking</code> branch, we can now get the first trace for every distinct result, along with its complexity:</p>
<pre class="haskell"><code>results :: Way -&gt; MemType -&gt; IO ()
results way memtype = do
  let settings = set lequality (Just (==))
               $ fromWayAndMemType way memtype
  res &lt;- runSCTWithSettings settings storesAreTransitivelyVisible
  flip mapM_ res $ \(efa, trace) -&gt;
    putStrLn (show efa ++ &quot;\t&quot; ++ showTrace trace ++ &quot;\t&quot; ++ show (complexity trace))</code></pre>
<p>Here are the results for systematic testing:</p>
<pre><code>λ&gt; results (systematically defaultBounds) SequentialConsistency
Right (1,0,1)   S0------------S1---S0--S2-----S0--S3-----S0--   (0,0,7,24)
Right (0,0,1)   S0------------S2-----S1---S0---S3-----S0--      (0,0,6,24)
Right (0,0,0)   S0------------S2-P3-----S1---S0--S2----S0---    (0,1,6,23)
Right (1,0,0)   S0------------S3-----S1---S0--S2-----S0---      (0,0,6,24)

λ&gt; results (systematically defaultBounds) TotalStoreOrder
Right (1,0,1)   S0------------S1---S0--S2-----S0--S3-----S0--   (0,0,7,24)
Right (0,0,1)   S0------------S1-P2-----S1--S0---S3-----S0--    (0,1,6,23)
Right (0,0,0)   S0------------S1-P2---P3-----S1--S0--S2--S0---  (0,2,6,22)
Right (1,0,0)   S0------------S1-P3-----S1--S0--S2-----S0---    (0,1,6,23)

λ&gt; results (systematically defaultBounds) PartialStoreOrder
Right (1,0,1)   S0------------S1---S0--S2-----S0--S3-----S0--   (0,0,7,24)
Right (0,0,1)   S0------------S1-P2-----S1--S0---S3-----S0--    (0,1,6,23)
Right (0,0,0)   S0------------S1-P2---P3-----S1--S0--S2--S0---  (0,2,6,22)
Right (1,0,0)   S0------------S1-P3-----S1--S0--S2-----S0---    (0,1,6,23)</code></pre>
<p>Pretty messy, right? Here’s the results for <em>random</em> testing:</p>
<pre><code>λ&gt; results (randomly (mkStdGen 0) 100) SequentialConsistency
Right (1,0,1)   S0-----P1-P0----P2-P1-P0-P3-P1-S2-P3--P0-P3-P0-P3-S2-P0-S2-P0--P2-S0-   (0,15,5,9)
Right (0,0,1)   S0-------P2-P1-P2-P0--P2-P0-P1-P0---S2-P3-P0-P2-S3---P1-S3-S0--         (0,12,5,12)
Right (1,0,0)   S0------------S3-----S1-P2-P1-P0--S2---P1-S0---                         (0,4,5,20)
Right (0,0,0)   S0---------P2-P0--P3-P0-S3--P2-P3-P2--P3-S2-S1--P0----                  (0,9,4,15)

λ&gt; results (randomly (mkStdGen 0) 100) TotalStoreOrder
Right (1,0,1)   S0-----P1--P0-P1-S0-P2--C-S0---P2-P3-P2--S3-P0-P3-P0---S3-P0-P3-S0-     (1,13,6,11)
Right (0,0,1)   S0----P1-P0-----P2--P0--P2-P0-S2--S3-P1-P0---S1-S3----S0--              (0,8,6,16)
Right (0,0,0)   S0--------P2-P0--P3-P2-P0-P3-P2-C-S0-S3---S2--S1-C-S1-P0----            (2,10,6,14)

λ&gt; results (randomly (mkStdGen 0) 100) PartialStoreOrder
Right (1,0,1)   S0-----P1--P0-P1-S0-P2--C-S0---P2-P3-P2--S3-P0-P3-P0---S3-P0-P3-S0-     (1,13,6,11)
Right (0,0,1)   S0----P1-P0-----P2--P0--P2-P0-S2--S3-P1-P0---S1-S3----S0--              (0,8,6,16)
Right (0,0,0)   S0--------P2-P0--P3-P2-P0-P3-P2-C-S0-S3---S2--S1-C-S1-P0----            (2,10,6,14)</code></pre>
<p>Yikes!</p>
<p>The complexity metric I defined counts four things:</p>
<ol type="1">
<li>The number of relaxed-memory commit actions</li>
<li>The number of pre-emptive context switches</li>
<li>The number of non-pre-emptive context switches</li>
<li>The number of continues</li>
</ol>
<p>I would much rather read a long trace where the only context switches are when threads block, than a short one which is rapidly jumping between threads. So, given two equivalent traces, I will always prefer the one with a lexicographically smaller complexity-tuple.</p>
<h2 id="trace-simplification">Trace simplification</h2>
<p>The key idea underpinning trace simplification is that dejafu can tell when two scheduling decisions can be swapped without changing the behaviour of the program. I talked about this idea in the <a href="hedgehog-dejafu.html">Using Hedgehog to Test Déjà Fu</a> memo. So we can implement transformations which are guaranteed to preserve semantics <em>without needing to verify this by re-running the test case</em>.</p>
<p>Although we don’t need to re-run the test case at all, the <code>183-shrinking</code> branch currently does, but only once at the end after the minimum has been found. This is because it’s easier to generate a simpler sequence of scheduling decisions and use dejafu to produce the corresponding trace than it is to produce a simpler trace directly. This is still strictly better than a typical shrinking algorithm, which would re-run the test case after <em>each</em> shrinking step, rather than only at the end.</p>
<p>Rather than drag this out, here’s what those random traces simplify to:</p>
<pre class="haskell"><code>resultsS :: Way -&gt; MemType -&gt; IO ()
resultsS way memtype = do
  let settings = set lsimplify True
               . set lequality (Just (==))
               $ fromWayAndMemType way memtype
  res &lt;- runSCTWithSettings settings storesAreTransitivelyVisible
  flip mapM_ res $ \(efa, trace) -&gt;
    putStrLn (show efa ++ &quot;\t&quot; ++ showTrace trace ++ &quot;\t&quot; ++ show (complexity trace))</code></pre>
<pre><code>λ&gt; resultsS (randomly (mkStdGen 0) 100) SequentialConsistency
Right (1,0,1)   S0----------P1---S2--P3-----S0---S2---S0---     (0,2,5,22)
Right (0,0,1)   S0----------P2-P1-P2-P1--S0---S2---S3-----S0--- (0,4,5,20)
Right (1,0,0)   S0------------S3-----S1---S0--S2----P0---       (0,1,5,23)
Right (0,0,0)   S0------------S3--P2-----S3---S1--P0----        (0,2,4,22)

λ&gt; resultsS (randomly (mkStdGen 0) 100) TotalStoreOrder
Right (1,0,1)   S0----------P1---S2-----S0----S3-----S0--       (0,1,5,23)
Right (0,0,1)   S0----------P1-P2-----S0--S1--S0---S3-----S0--  (0,2,6,22)
Right (0,0,0)   S0----------P2--P3-----S0--S2---S1--P0----      (0,3,4,21)

λ&gt; resultsS (randomly (mkStdGen 0) 100) PartialStoreOrder
Right (1,0,1)   S0----------P1---S2-----S0----S3-----S0--       (0,1,5,23)
Right (0,0,1)   S0----------P1-P2-----S0--S1--S0---S3-----S0--  (0,2,6,22)
Right (0,0,0)   S0----------P2--P3-----S0--S2---S1--P0----      (0,3,4,21)</code></pre>
<p>This is much better.</p>
<p>There are two simplification phases: a preparation phase, which puts the trace into a normal form and prunes unnecessary commits; and an iteration phase, which repeats a step function until a fixed point is reached (or the iteration limit is).</p>
<h3 id="preparation">Preparation</h3>
<p>The preparation phase has two steps: first we put the trace into <em>lexicographic normal form</em>, then we prune unnecessary commits.</p>
<p>We put a trace in lexicographic normal form by sorting by thread ID, where only independent actions can be swapped:</p>
<pre class="haskell"><code>lexicoNormalForm :: MemType -&gt; [(ThreadId, ThreadAction)] -&gt; [(ThreadId, ThreadAction)]
lexicoNormalForm memtype = go where
  go trc =
    let trc&#39; = bubble initialDepState trc
    in if trc == trc&#39; then trc else go trc&#39;

  bubble ds (t1@(tid1, ta1):t2@(tid2, ta2):trc)
    | independent ds tid1 ta1 tid2 ta2 &amp;&amp; tid2 &lt; tid1 = bgo ds t2 (t1 : trc)
    | otherwise = bgo ds t1 (t2 : trc)
  bubble _ trc = trc

  bgo ds t@(tid, ta) trc = t : bubble (updateDepState memtype ds tid ta) trc</code></pre>
<p>If simplification only put traces into lexicographic normal form, we would get these results:</p>
<pre><code>λ&gt; resultsS (randomly (mkStdGen 0) 100) SequentialConsistency
Right (1,0,1)   S0-----------P1---S2--P0--S2--P0-P3----P0--             (0,5,3,19)
Right (0,0,1)   S0-----------P2-P1-P2-P1-P0--S2--P0-P1-S2-S3----P0--    (0,8,4,16)
Right (1,0,0)   S0------------S3----P1--P0--S1-S2----P0---              (0,3,4,21)
Right (0,0,0)   S0------------S2-P3--P2----S3--P1--P0----               (0,4,3,20)

λ&gt; resultsS (randomly (mkStdGen 0) 100) TotalStoreOrder
Right (1,0,1)   S0-------P1---S2--C-S0-----P2--P0--S2-S3----P0--        (1,5,5,19)
Right (0,0,1)   S0-----------P1-P2--P0-S1-P0-P2--P0--S1-S2-S3----P0--   (0,7,5,17)
Right (0,0,0)   S0-----------P2---P3--C-S0-S2--S3--P1-C-S1-P0----       (2,6,5,18)

λ&gt; resultsS (randomly (mkStdGen 0) 100) PartialStoreOrder
Right (1,0,1)   S0-------P1---S2--C-S0-----P2--P0--S2-S3----P0--        (1,5,5,19)
Right (0,0,1)   S0-----------P1-P2--P0-S1-P0-P2--P0--S1-S2-S3----P0--   (0,7,5,17)
Right (0,0,0)   S0-----------P2---P3--C-S0-S2--S3--P1-C-S1-P0----       (2,6,5,18)</code></pre>
<p>These are better than they were, but we can do better still.</p>
<p>After putting the trace into lexicographic normal form, we delete any commit actions which are followed by any number of independent actions and then a memory barrier:</p>
<pre class="haskell"><code>dropCommits :: MemType -&gt; [(ThreadId, ThreadAction)] -&gt; [(ThreadId, ThreadAction)]
dropCommits SequentialConsistency = id
dropCommits memtype = go initialDepState where
  go ds (t1@(tid1, ta1@(CommitCRef _ _)):t2@(tid2, ta2):trc)
    | isBarrier (simplifyAction ta2) = go ds (t2:trc)
    | independent ds tid1 ta1 tid2 ta2 = t2 : go (updateDepState memtype ds tid2 ta2) (t1:trc)
  go ds (t@(tid,ta):trc) = t : go (updateDepState memtype ds tid ta) trc
  go _ [] = []</code></pre>
<p>Such commits don’t affect the behaviour of the program at all, as all buffered writes gets flushed when the memory barrier happens.</p>
<p>If simplification only did the preparation phase, we would get these results:</p>
<pre><code>λ&gt; resultsS (randomly (mkStdGen 0) 100) SequentialConsistency
Right (1,0,1)   S0-----------P1---S2--P0--S2--P0-P3----P0--             (0,5,3,19)
Right (0,0,1)   S0-----------P2-P1-P2-P1-P0--S2--P0-P1-S2-S3----P0--    (0,8,4,16)
Right (1,0,0)   S0------------S3----P1--P0--S1-S2----P0---              (0,3,4,21)
Right (0,0,0)   S0------------S2-P3--P2----S3--P1--P0----               (0,4,3,20)

λ&gt; resultsS (randomly (mkStdGen 0) 100) TotalStoreOrder
Right (1,0,1)   S0-------P1---S2--P0-----P2--P0--S2-S3----P0--          (0,5,4,19)
     ^-- better than just lexicoNormalForm
Right (0,0,1)   S0-----------P1-P2--P0-S1-P0-P2--P0--S1-S2-S3----P0--   (0,7,5,17)
Right (0,0,0)   S0-----------P2---P3--P0-S2--S3--P1--P0----             (0,5,3,19)
     ^-- better than just lexicoNormalForm

λ&gt; resultsS (randomly (mkStdGen 0) 100) PartialStoreOrder
Right (1,0,1)   S0-------P1---S2--P0-----P2--P0--S2-S3----P0--          (0,5,4,19)
     ^-- better than just lexicoNormalForm
Right (0,0,1)   S0-----------P1-P2--P0-S1-P0-P2--P0--S1-S2-S3----P0--   (0,7,5,17)
Right (0,0,0)   S0-----------P2---P3--P0-S2--S3--P1--P0----             (0,5,3,19)
     ^-- better than just lexicoNormalForm</code></pre>
<h3 id="iteration">Iteration</h3>
<p>The iteration phase attempts to reduce context switching by pushing actions forwards, or pulling them backwards, through the trace.</p>
<p>If we have the trace <code>[(tid1, act1), (tid2, act2), (tid1, act3)]</code>, where <code>act2</code> and <code>act3</code> are independent, the “pull back” transformation would re-order that to <code>[(tid1, act1), (tid1, act3), (tid2, act2)]</code>.</p>
<p>In contrast, if <code>act1</code> and <code>act2</code> were independent, the “push forward” transformation would re-order that to <code>[(tid2, act2), (tid1, act1), (tid1, act3)]</code>. The two transformations are almost, but not quite opposites.</p>
<p>Pull-back walks through the trace and, at every context switch, looks forward to see if there is a single action of the original thread it can put before the context switch:</p>
<pre class="haskell"><code>pullBack :: MemType -&gt; [(ThreadId, ThreadAction)] -&gt; [(ThreadId, ThreadAction)]
pullBack memtype = go initialDepState where
  go ds (t1@(tid1, ta1):trc@((tid2, _):_)) =
    let ds&#39; = updateDepState memtype ds tid1 ta1
        trc&#39; = if tid1 /= tid2
               then maybe trc (uncurry (:)) (findAction tid1 ds&#39; trc)
               else trc
    in t1 : go ds&#39; trc&#39;
  go _ trc = trc

  findAction tid0 = fgo where
    fgo ds (t@(tid, ta):trc)
      | tid == tid0 = Just (t, trc)
      | otherwise = case fgo (updateDepState memtype ds tid ta) trc of
          Just (ft@(ftid, fa), trc&#39;)
            | independent ds tid ta ftid fa -&gt; Just (ft, t:trc&#39;)
          _ -&gt; Nothing
    fgo _ _ = Nothing</code></pre>
<p>Push-forward walks through the trace and, at every context switch, looks forward to see if the last action of the original thread can be put at its next execution:</p>
<pre class="haskell"><code>pushForward :: MemType -&gt; [(ThreadId, ThreadAction)] -&gt; [(ThreadId, ThreadAction)]
pushForward memtype = go initialDepState where
  go ds (t1@(tid1, ta1):trc@((tid2, _):_)) =
    let ds&#39; = updateDepState memtype ds tid1 ta1
    in if tid1 /= tid2
       then maybe (t1 : go ds&#39; trc) (go ds) (findAction tid1 ta1 ds trc)
       else t1 : go ds&#39; trc
  go _ trc = trc

  findAction tid0 ta0 = fgo where
    fgo ds (t@(tid, ta):trc)
      | tid == tid0 = Just ((tid0, ta0) : t : trc)
      | independent ds tid0 ta0 tid ta = (t:) &lt;$&gt; fgo (updateDepState memtype ds tid ta) trc
      | otherwise = Nothing
    fgo _ _ = Nothing</code></pre>
<p>The iteration process just repeats <code>pushForward memtype . pullBack memtype</code>.</p>
<p>If it only used <code>pullBack</code>, we would get these results:</p>
<pre><code>λ&gt; resultsS (randomly (mkStdGen 0) 100) SequentialConsistency
Right (1,0,1)   S0-----------P1---S2---P0--S2--S0-P3-----S0--           (0,3,5,21)
Right (0,0,1)   S0-----------P2-P1-P2--P1--S0--S2--S0-P3-----S0--       (0,5,5,19)
Right (1,0,0)   S0------------S3-----S1---S0--S2----P0---               (0,1,5,23)
Right (0,0,0)   S0------------S2-P3---P2----S3--S1--P0----              (0,3,4,21)

λ&gt; resultsS (randomly (mkStdGen 0) 100) TotalStoreOrder
Right (1,0,1)   S0-----------P1---S2-----S0---S3-----S0--               (0,1,5,23)
Right (0,0,1)   S0-----------P1-P2-----S0-S1--S0---S3-----S0--          (0,2,6,22)
Right (0,0,0)   S0-----------P2---P3-----S0-S2--S1--P0----              (0,3,4,21)

λ&gt; resultsS (randomly (mkStdGen 0) 100) PartialStoreOrder
Right (1,0,1)   S0-----------P1---S2-----S0---S3-----S0--               (0,1,5,23)
Right (0,0,1)   S0-----------P1-P2-----S0-S1--S0---S3-----S0--          (0,2,6,22)
Right (0,0,0)   S0-----------P2---P3-----S0-S2--S1--P0----              (0,3,4,21)</code></pre>
<p>With no exception, iterating <code>pullBack</code> is an improvement over just doing preparation.</p>
<p>If it only used <code>pushForward</code>, we would get these results:</p>
<pre><code>λ&gt; resultsS (randomly (mkStdGen 0) 100) SequentialConsistency
Right (1,0,1)   S0-------P1---S2--P0------S2--P3----P0---               (0,4,3,20)
Right (0,0,1)   S0-------P2-P1-P2-P1-P0------S1-S2---S3----P0---        (0,6,4,18)
Right (1,0,0)   S0------------S3----P1--P0--S1-S2----P0---              (0,3,4,21)
     ^-- no improvement over preparation
Right (0,0,0)   S0------------S3--P2-----S3--P1--P0----                 (0,3,3,21)

λ&gt; resultsS (randomly (mkStdGen 0) 100) TotalStoreOrder
Right (1,0,1)   S0----P1---S0---P2----P0-------S2-S3----P0--            (0,4,4,20)
Right (0,0,1)   S0-------P1-P2--P0-----S1-P2--P0---S1-S2-S3----P0--     (0,6,5,18)
Right (0,0,0)   S0----------P2--P3--P0--S2---S3--P1--P0----             (0,5,3,19)
     ^-- no improvement over preparation

λ&gt; resultsS (randomly (mkStdGen 0) 100) PartialStoreOrder
Right (1,0,1)   S0----P1---S0---P2----P0-------S2-S3----P0--            (0,4,4,20)
Right (0,0,1)   S0-------P1-P2--P0-----S1-P2--P0---S1-S2-S3----P0--     (0,6,5,18)
Right (0,0,0)   S0----------P2--P3--P0--S2---S3--P1--P0----             (0,5,3,19)
     ^-- no improvement over preparation</code></pre>
<p>With three exceptions, where the traces didn’t change, iterating <code>pushForward</code> is an improvement over just doing preparation.</p>
<p>We’ve already seen the results if we combine them:</p>
<pre><code>λ&gt; resultsS (randomly (mkStdGen 0) 100) SequentialConsistency
Right (1,0,1)   S0----------P1---S2--P3-----S0---S2---S0---     (0,2,5,22)
Right (0,0,1)   S0----------P2-P1-P2-P1--S0---S2---S3-----S0--- (0,4,5,20)
Right (1,0,0)   S0------------S3-----S1---S0--S2----P0---       (0,1,5,23)
     ^-- same as pullBack, which is better than pushForward
Right (0,0,0)   S0------------S3--P2-----S3---S1--P0----        (0,2,4,22)

λ&gt; resultsS (randomly (mkStdGen 0) 100) TotalStoreOrder
Right (1,0,1)   S0----------P1---S2-----S0----S3-----S0--       (0,1,5,23)
     ^-- same as pullBack, which is better than pushForward
Right (0,0,1)   S0----------P1-P2-----S0--S1--S0---S3-----S0--  (0,2,6,22)
     ^-- same as pullBack, which is better than pushForward
Right (0,0,0)   S0----------P2--P3-----S0--S2---S1--P0----      (0,3,4,21)

λ&gt; resultsS (randomly (mkStdGen 0) 100) PartialStoreOrder
Right (1,0,1)   S0----------P1---S2-----S0----S3-----S0--       (0,1,5,23)
     ^-- same as pullBack, which is better than pushForward
Right (0,0,1)   S0----------P1-P2-----S0--S1--S0---S3-----S0--  (0,2,6,22)
     ^-- same as pullBack, which is better than pushForward
Right (0,0,0)   S0----------P2--P3-----S0--S2---S1--P0----      (0,3,4,21)</code></pre>
<h2 id="next-steps">Next steps</h2>
<p>I think what I have right now is pretty good. It’s definitely a vast improvement over not doing any simplification.</p>
<p><em>But</em>, no random traces get simplified to the corresponding systematic traces, which is a little disappointing. I think that’s because the current passes just try to reduce context switches of any form, whereas really I want to reduce pre-emptive context switches more than non-pre-emptive ones.</p>

      ]]>
    </summary>
  </entry>
  
  <entry>
    <title>Using Hedgehog to Test Déjà Fu</title>
    <link href="https://memo.barrucadu.co.uk/hedgehog-dejafu.html" />
    <id>https://memo.barrucadu.co.uk/hedgehog-dejafu.html</id>
    <published>2018-02-11T00:00:00Z</published>
    <updated>2018-02-11T00:00:00Z</updated>
    <summary type="html">
      <![CDATA[
<p>Déjà Fu is a concurrency testing library, and one thing you definitely <em>don’t</em> want to do when testing concurrent programs is to try every possible interleaving of threads.</p>
<p>Trying every possible interleaving will give you, in general, an exponential blow-up of the executions you need to perform as your test case grows in size. The core testing algorithm we use, a variant of dynamic partial-order reduction (DPOR)<a href="hedgehog-dejafu.html#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>, attempts to reduce this blow-up. DPOR identifies actions which are <em>dependent</em>, and only tries interleavings which permute dependent actions.</p>
<p>Here are some examples:</p>
<ul>
<li><p>It doesn’t matter which order two threads execute <code>readMVar</code>, for the same <code>MVar</code>. These actions are <em>independent</em>.</p></li>
<li><p>It does matter which order two threads execute <code>putMVar</code>, for the same <code>MVar</code>. These actions are <em>dependent</em>.</p></li>
<li><p>It doesn’t matter which order two threads execute <code>putMVar</code> for different <code>MVar</code>s. These actions are <em>independent</em>.</p></li>
</ul>
<p>Two actions are dependent if the order in which they are performed matters.</p>
<p>So the intuition behind DPOR is that most actions in a concurrent program are <em>independent</em>. DPOR won’t help you much if you have a single piece of shared state which every thread is hitting, but most concurrent programs aren’t like that. The worst case is still a terrible exponential blow-up, but the average case is much better.</p>
<p>The dependency relation is <em>core</em> part of Déjà Fu today. It has impacts on both performance and correctness. If it says two actions are dependent when they are not, then we may see unnecessary interleavings tried. If it says two actions are not dependent when they really are, then we may miss necessary interleavings.</p>
<p>Being such an important component, it must be well-tested, right? Well, sort of. The Déjà Fu testsuite mostly consists of small concurrent programs together with a list of expected outputs, testing that Déjà Fu finds all the nondeterminism in the program. This does exercise the dependency relation, but only very indirectly.</p>
<h2 id="the-idea">The Idea</h2>
<p>There things would have remained had I not experienced one of those coincidence-driven flashes of insight:</p>
<ul>
<li><p><a href="https://github.com/aherrmann">aherrmann</a> opened an <a href="https://github.com/barrucadu/dejafu/issues/181">issue on GitHub</a> asking how to take an execution trace and replay it.</p></li>
<li><p><a href="https://www.reddit.com/user/agnishom">agnishom</a> posted a <a href="https://www.reddit.com/r/algorithms/comments/7vo0el/checking_equivalence_of_trace_elements/">thread on /r/algorithms</a> asking how to check the equivalence of traces where only some elements commute.</p></li>
</ul>
<p>I had my idea. I can <em>directly</em> test the dependency relation like so:</p>
<ol type="1">
<li>Execute a concurrent program.</li>
<li>Normalise its execution trace in some way.</li>
<li>“Replay” the normalised trace.</li>
<li>Assert that the result is the same.</li>
</ol>
<h2 id="normalising-traces">Normalising Traces</h2>
<p>So, what is a good normal form for a trace? I tried out a few approaches here, but there was one I kept coming back to: we should shuffle around independent actions to keep the program on the main thread for as long as possible.</p>
<p>There are two reasons I think this works well. (1) The traces we get will be easier for a human to read, as the program will stay on its main thread and only execute another thread where necessary. (2) A Haskell program terminates when the main thread terminates, so by executing the main thread as much as possible, we may find that some actions don’t need to be executed at all.</p>
<p>So firstly we need to know when two actions commute. Let’s just use the dependency relation for that:</p>
<pre class="haskell"><code>-- | Check if two actions commute.
independent
  :: DepState
  -&gt; (ThreadId, ThreadAction)
  -&gt; (ThreadId, ThreadAction)
  -&gt; Bool
independent ds (tid1, ta1) (tid2, ta2) = not (dependent ds tid1 ta1 tid2 ta2)</code></pre>
<p>The <code>DepState</code> parameter tracks information about the history of the execution, allowing us to make better decisions. For example: while in general it matters in which order two <code>putMVar</code>s to the same <code>MVar</code> happen; it <em>doesn’t</em> matter if the <code>MVar</code> is already full, as both actions will block without achieving anything.</p>
<p>The approach works well in practice, but has been the source of <em>so many</em> off-by-one errors. Even while writing this memo!</p>
<p>So now onto trace normalisation. The easiest way to do it is bubble sort, but with an additional constraint on when we can swap things:</p>
<ol type="1">
<li>For every adjacent pair of items <code>x</code> and <code>y</code> in the trace:
<ol type="1">
<li>If <code>x</code> and <code>y</code> commute and <code>thread_id y &lt; thread_id x</code>:
<ol type="1">
<li>Swap <code>x</code> and <code>y</code>.</li>
</ol></li>
<li>Update the <code>DepState</code> and continue to the next pair.</li>
</ol></li>
<li>Repeat until there are no more changes.</li>
</ol>
<p>And here’s the code:</p>
<pre class="haskell"><code>-- | Rewrite a trace into a canonical form.
normalise
  :: [(ThreadId, ThreadAction)]
  -&gt; [(ThreadId, ThreadAction)]
normalise trc0 = if changed then normalise trc&#39; else trc&#39;
 where
  (changed, trc&#39;) = bubble initialDepState False trc0

  bubble ds flag ((x@(tid1, _)):(y@(tid2, _)):trc)
    | independent ds x y &amp;&amp; tid2 &lt; tid1 = go ds True y (x : trc)
    | otherwise = go ds flag x (y : trc)
  bubble _ flag trc = (flag, trc)

  go ds flag t@(tid, ta) trc =
    second (t :) (bubble (updateDepState ds tid ta) flag trc)</code></pre>
<h2 id="testing-normalised-traces">Testing Normalised Traces</h2>
<p>Now we need a scheduler which can play a given list of scheduling decisions. This isn’t built in, but we can make one. Schedulers look like this:</p>
<pre class="haskell"><code>-- from Test.DejaFu.Schedule
newtype Scheduler state = Scheduler
  { scheduleThread
    :: Maybe (ThreadId, ThreadAction)
    -&gt; NonEmpty (ThreadId, Lookahead)
    -&gt; state
    -&gt; (Maybe ThreadId, state)
  }</code></pre>
<p>A scheduler is a stateful function, which takes the previously scheduled action and the list of runnable threads, and gives back a thread to execute. We don’t care about those parameters. We just want to play a fixed list of scheduling decisions. And here is how we do that:</p>
<pre class="haskell"><code>-- | Execute a concurrent program by playing a list of scheduling decisions.
play
  :: MemType
  -&gt; [ThreadId]
  -&gt; ConcIO a
  -&gt; IO (Either Failure a, [ThreadId], Trace)
play = runConcurrent (Scheduler sched)
 where
  sched _ _ (t:ts) = (Just t, ts)
  sched _ _ [] = (Nothing, [])</code></pre>
<p>Now all the background is in place, so we can test what we want to test: that an execution, and the play-back of its normalised trace, give the same result. For reasons which will become apparent in the next section, I’m going to parameterise over the normalisation function:</p>
<pre class="haskell"><code>-- | Execute a concurrent program with a random scheduler, normalise its trace,
-- execute the normalised trace, and return both results.
runNorm
  :: ([(ThreadId, ThreadAction)] -&gt; [(ThreadId, ThreadAction)])
  -&gt; Int
  -&gt; MemType
  -&gt; ConcIO a
  -&gt; IO (Either Failure a, [ThreadId], Either Failure a, [ThreadId])
runNorm norm seed memtype conc = do
  let g = mkStdGen seed                                       -- 1
  (efa1, _, trc) &lt;- runConcurrent randomSched memtype g conc
  let                                                         -- 2
    trc&#39; = tail
      ( scanl
        (\(t, _) (d, _, a) -&gt; (tidOf t d, a))
        (initialThread, undefined)
        trc
      )
  let tids1 = map fst trc&#39;
  let tids2 = map fst (norm trc&#39;)                             -- 3
  (efa2, s, _) &lt;- play memtype tids2 conc
  let truncated = take (length tids2 - length s) tids2        -- 4
  pure (efa1, tids1, efa2, truncated)</code></pre>
<p>There’s a lot going on here, so let’s break it down:</p>
<ol type="1">
<li><p>We execute the program with the built-in random scheduler, using the provided seed.</p></li>
<li><p>The trace that <code>runConcurrent</code> gives us is in the form <code>[(Decision,    [(ThreadId, Lookahead)], ThreadAction)]</code>, whereas we want a <code>[(ThreadId, ThreadAction)]</code>. So this scan just changes the format. It’s a scan rather than a map because to convert a <code>Decision</code> into a <code>ThreadId</code> potentially requires knowing what the previous thread was.</p></li>
<li><p>We normalise the trace, and run it again.</p></li>
<li><p>If the entire normalised trace wasn’t used up, then it has some unnecessary suffix (because the main thread is now terminating sooner). So we make the normalised trace easier to read by chopping off any such suffix.</p></li>
</ol>
<p>Finally, we can write a little function to test using the <code>normalise</code> function:</p>
<pre class="haskell"><code>-- | Execute a concurrent program with a random scheduler, normalise its trace,
-- execute the normalised trace, and check that both give the same result.
testNormalise
  :: (Eq a, Show a)
  =&gt; Int
  -&gt; MemType
  -&gt; ConcIO a
  -&gt; IO Bool
testNormalise seed memtype conc = do
  (efa1, tids1, efa2, tids2) &lt;- runNorm normalise seed memtype conc
  unless (efa1 == efa2) $ do
    putStrLn   &quot;Mismatched result!&quot;
    putStrLn $ &quot;      expected: &quot; ++ show efa1
    putStrLn $ &quot;       but got: &quot; ++ show efa2
    putStrLn   &quot;&quot;
    putStrLn $ &quot;rewritten from: &quot; ++ show tids1
    putStrLn $ &quot;            to: &quot; ++ show tids2
  pure (efa1 == efa2)</code></pre>
<p>And does it work? Let’s copy two example programs from the Test.DejaFu docs:</p>
<pre class="haskell"><code>-- from Test.DejaFu
example1
  :: MonadConc m
  =&gt; m String
example1 = do
  var &lt;- newEmptyMVar
  fork (putMVar var &quot;hello&quot;)
  fork (putMVar var &quot;world&quot;)
  readMVar var

example2
  :: MonadConc m
  =&gt; m (Bool, Bool)
example2 = do
  r1 &lt;- newCRef False
  r2 &lt;- newCRef False
  x &lt;- spawn $ writeCRef r1 True &gt;&gt; readCRef r2
  y &lt;- spawn $ writeCRef r2 True &gt;&gt; readCRef r1
  (,) &lt;$&gt; readMVar x &lt;*&gt; readMVar y</code></pre>
<p>And then test them:</p>
<pre><code>&gt; testNormalise 0 TotalStoreOrder example1
True
&gt; testNormalise 0 TotalStoreOrder example2
True</code></pre>
<p>According to my very unscientific method, everything works perfectly!</p>
<h2 id="enter-hedgehog">Enter Hedgehog</h2>
<p>You can probably see where this is going: just supplying <em>one</em> random seed and <em>one</em> memory model is a poor way to test things. Ah, if only we had some sort of tool to generate arbitrary values for us!</p>
<p>But that’s not all: if the dependency relation is correct, then <em>any</em> permutation of independent actions should give the same result, not just the one which <code>normalise</code> implements. So before we introduce <a href="https://hackage.haskell.org/package/hedgehog">Hedgehog</a> and arbitrary values, let’s make something a little more chaotic:</p>
<pre class="haskell"><code>-- | Shuffle independent actions in a trace according to the given list.
shuffle
  :: [Bool]
  -&gt; [(ThreadId, ThreadAction)]
  -&gt; [(ThreadId, ThreadAction)]
shuffle = go initialDepState
 where
  go ds (f:fs) (t1:t2:trc)
    | independent ds t1 t2 &amp;&amp; f = go&#39; ds fs t2 (t1 : trc)
    | otherwise = go&#39; ds fs t1 (t2 : trc)
  go _ _ trc = trc

  go&#39; ds fs t@(tid, ta) trc =
    t : go (updateDepState ds tid ta) fs trc</code></pre>
<p>In <code>normalise</code>, two independent actions will <em>always</em> be re-ordered if it gets us closer to the canonical form. However, in <code>shuffle</code>, two independent actions will either be re-ordered or not, depending on the supplied list of <code>Bool</code>.</p>
<p>This is much better for testing our dependency relation, as we can now get far more re-orderings which <em>all</em> should satisfy the same property: that no matter how the independent actions in a trace are shuffled, we get the same result.</p>
<p>I think it’s about time to bring out Hedgehog:</p>
<pre class="haskell"><code>-- | Execute a concurrent program with a random scheduler, arbitrarily permute
-- the independent actions in the trace, and check that we get the same result
-- out.
hog :: (Eq a, Show a) =&gt; ConcIO a -&gt; IO Bool
hog conc = Hedgehog.check . property $ do
  mem &lt;- forAll Gen.enumBounded                               -- 1
  seed &lt;- forAll $ Gen.int (Range.linear 0 100)
  fs &lt;- forAll $ Gen.list (Range.linear 0 100) Gen.bool

  (efa1, tids1, efa2, tids2) &lt;- liftIO                        -- 2
    $ runNorm (shuffle fs) seed mem conc
  footnote (&quot;            to: &quot; ++ show tids2)                 -- 3
  footnote (&quot;rewritten from: &quot; ++ show tids1)
  efa1 === efa2</code></pre>
<p>Let’s break that down:</p>
<ol type="1">
<li><p>We’re telling Hedgehog that this property should hold for all memory models, all seeds, and all <code>Bool</code>-lists. Unlike most Haskell property-testing libraries, Hedgehog takes generator functions rather than using a typeclass. I think this is nicer.</p></li>
<li><p>We run our program, normalise it, and get all the results just as before.</p></li>
<li><p>We add some footnotes: messages which Hedgehog will display along with a failure. For some reason these get displayed in reverse order.</p></li>
</ol>
<p>Alright, let’s see if Hedgehog finds any bugs for us:</p>
<pre><code>&gt; hog example1
  ? &lt;interactive&gt; failed after 3 tests and 1 shrink.

       ??? extra.hs ???
    82 ? hog :: (Eq a, Show a) =&gt; ConcIO a -&gt; IO Bool
    83 ? hog conc = Hedgehog.check . property $ do
    84 ?   mem &lt;- forAll Gen.enumBounded
       ?   ? SequentialConsistency
    85 ?   seed &lt;- forAll $ Gen.int (Range.linear 0 100)
       ?   ? 0
    86 ?   fs &lt;- forAll $ Gen.list (Range.linear 0 100) Gen.bool
       ?   ? [ False , True ]
    87 ?
    88 ?   (efa1, tids1, efa2, tids2) &lt;- liftIO
    89 ?     $ runNorm (shuffle fs) seed mem conc
    90 ?   footnote (&quot;            to: &quot; ++ show tids2)
    91 ?   footnote (&quot;rewritten from: &quot; ++ show tids1)
    92 ?   efa1 === efa2
       ?   ^^^^^^^^^^^^^
       ?   ? Failed (- lhs =/= + rhs)
       ?   ? - Right &quot;hello&quot;
       ?   ? + Left InternalError

    rewritten from: [main,main,1,main,1,2,main,2,main]
                to: [main,1]

    This failure can be reproduced by running:
    &gt; recheck (Size 2) (Seed 1824012233418733250 (-4876494268681827407)) &lt;property&gt;

False</code></pre>
<p>It did! And look at that output! Magical! I must see if I can get Déjà Fu to give annotated source output like that.</p>
<p>Let’s look at <code>example1</code> again:</p>
<pre class="haskell"><code>do
  var &lt;- newEmptyMVar
  fork (putMVar var &quot;hello&quot;)
  fork (putMVar var &quot;world&quot;)
  readMVar var</code></pre>
<p>Oh dear, our rewritten trace is trying to execute thread <code>1</code> immediately after the first action of the main thread. The first action of the main thread is <code>newEmptyMVar</code>: thread <code>1</code> doesn’t exist at that point!</p>
<p>Let’s change our <code>independent</code> function to say that an action is dependent with the fork which creates its thread:</p>
<pre class="haskell"><code>independent ds (tid1, ta1) (tid2, ta2)
  | ta1 == Fork tid2 = False
  | ta2 == Fork tid1 = False
  | otherwise = not (dependent ds tid1 ta1 tid2 ta2)</code></pre>
<p>How about now?</p>
<pre><code>&gt; hog example1
  ? &lt;interactive&gt; failed after 13 tests and 2 shrinks.

       ??? extra.hs ???
    82 ? hog :: (Eq a, Show a) =&gt; ConcIO a -&gt; IO Bool
    83 ? hog conc = Hedgehog.check . property $ do
    84 ?   mem &lt;- forAll Gen.enumBounded
       ?   ? SequentialConsistency
    85 ?   seed &lt;- forAll $ Gen.int (Range.linear 0 100)
       ?   ? 0
    86 ?   fs &lt;- forAll $ Gen.list (Range.linear 0 100) Gen.bool
       ?   ? [ True , True ]
    87 ?
    88 ?   (efa1, tids1, efa2, tids2) &lt;- liftIO
    89 ?     $ runNorm (shuffle fs) seed mem conc
    90 ?   footnote (&quot;            to: &quot; ++ show tids2)
    91 ?   footnote (&quot;rewritten from: &quot; ++ show tids1)
    92 ?   efa1 === efa2
       ?   ^^^^^^^^^^^^^
       ?   ? Failed (- lhs =/= + rhs)
       ?   ? - Right &quot;hello&quot;
       ?   ? + Left InternalError

    rewritten from: [main,main,1,main,1,2,main,2,main]
                to: [main,1]

    This failure can be reproduced by running:
    &gt; recheck (Size 12) (Seed 654387260079025817 (-6686572164463137223)) &lt;property&gt;

False</code></pre>
<p>Well, that failing trace looks exactly like the previous error. But the parameters are different: the first error happened with the list <code>[False, True]</code>, this requires the list <code>[True, True]</code>. So let’s think about what happens to the trace in this case.</p>
<ol type="1">
<li><p>We start with: <code>[(main, NewEmptyMVar 0), (main, Fork 1), (1,    PutMVar 0)]</code>.</p></li>
<li><p>The first two actions are independent, and the flag is <code>True</code>, so we swap them. We now have: <code>[(main, Fork 1), (main, NewEmptyMVar    1), (1, PutMVar 0)]</code>.</p></li>
<li><p>The second two actions are independent, and the flag is <code>True</code>, so we swap them. We now have: <code>[(main, Fork 1), (1, PutMVar 0),    (main, NewEmptyMVar 0)]</code>.</p></li>
</ol>
<p>We can’t actually re-order actions of the same thread, so we should never have swapped the first two. I suppose there’s another problem here, that no action on an <code>MVar</code> commutes with creating that <code>MVar</code>, but we should never be in a situation where that could happen. So we need another case in <code>independent</code>:</p>
<pre class="haskell"><code>independent ds (tid1, ta1) (tid2, ta2)
  | tid1 == tid2 = False
  | ta1 == Fork tid2 = False
  | ta2 == Fork tid1 = False
  | otherwise = not (dependent ds tid1 ta1 tid2 ta2)</code></pre>
<p>Our first example program works fine now:</p>
<pre><code>&gt; hog example1
  ? &lt;interactive&gt; passed 100 tests.
True</code></pre>
<p>The second is a little less happy:</p>
<pre><code>&gt; hog example2
  ? &lt;interactive&gt; failed after 48 tests and 9 shrinks.

       ??? extra.hs ???
    82 ? hog :: (Eq a, Show a) =&gt; ConcIO a -&gt; IO Bool
    83 ? hog conc = Hedgehog.check . property $ do
    84 ?   mem &lt;- forAll Gen.enumBounded
       ?   ? TotalStoreOrder
    85 ?   seed &lt;- forAll $ Gen.int (Range.linear 0 100)
       ?   ? 0
    86 ?   fs &lt;- forAll $ Gen.list (Range.linear 0 100) Gen.bool
       ?   ? [ False
       ?   ? , False
       ?   ? , False
       ?   ? , False
       ?   ? , False
       ?   ? , False
       ?   ? , False
       ?   ? , False
       ?   ? , False
       ?   ? , False
       ?   ? , False
       ?   ? , False
       ?   ? , False
       ?   ? , False
       ?   ? , True
       ?   ? ]
    87 ?
    88 ?   (efa1, tids1, efa2, tids2) &lt;- liftIO
    89 ?     $ runNorm (shuffle fs) seed mem conc
    90 ?   footnote (&quot;            to: &quot; ++ show tids2)
    91 ?   footnote (&quot;rewritten from: &quot; ++ show tids1)
    92 ?   efa1 === efa2
       ?   ^^^^^^^^^^^^^
       ?   ? Failed (- lhs =/= + rhs)
       ?   ? - Right ( False , True )
       ?   ? + Left InternalError

    rewritten from: [main,main,main,main,main,1,-1,1,1,main,1,main,main,main,main,2,-1,2,2,main,main]
                to: [main,main,main,main,main,1,-1,1,1,main,1,main,main,main,2,main,-1]

    This failure can be reproduced by running:
    &gt; recheck (Size 47) (Seed 2159662051602767058 (-7857629802164753123)) &lt;property&gt;

False</code></pre>
<p>This is a little trickier. Here’s my diagnosis:</p>
<ol type="1">
<li><p>It’s an <code>InternalError</code> again, which means we’re trying to execute a thread which isn’t runnable.</p></li>
<li><p>The memory model is <code>TotalStoreOrder</code>, and the thread we’re trying to execute is thread <code>-1</code>, a “fake” thread used in the relaxed memory implementation. So this is a relaxed memory bug.</p></li>
<li><p>The traces only differ in one place: where <code>main, 2, -1</code> is changed to <code>2, main, -1</code>. So the issue is caused by re-ordering <code>main</code> and thread <code>2</code>.</p></li>
<li><p>If the <code>main</code> action is a memory barrier, then thread <code>-1</code> will not exist after it.</p></li>
<li><p>So the <code>main</code> action is probably a memory barrier.</p></li>
</ol>
<p>Let’s push along those lines and add a case for memory barriers to <code>independent</code>:</p>
<pre class="haskell"><code>independent ds (tid1, ta1) (tid2, ta2)
  | tid1 == tid2 = False
  | ta1 == Fork tid2 = False
  | ta2 == Fork tid1 = False
  | otherwise = case (simplifyAction ta1, simplifyAction ta2) of
      (UnsynchronisedWrite _, a) | isBarrier a -&gt; False
      (a, UnsynchronisedWrite _) | isBarrier a -&gt; False
      _ -&gt; not (dependent ds tid1 ta1 tid2 ta2)</code></pre>
<p>Did we get it?</p>
<pre><code>&gt; hog example2
  ? &lt;interactive&gt; passed 100 tests.
True</code></pre>
<p>Great!</p>
<h2 id="bugs">Bugs?</h2>
<p>So, we explored the dependency relation with Hedgehog, and found three missing cases:</p>
<ol type="1">
<li><p>Two actions of the same thread are dependent.</p></li>
<li><p>Any action of a thread is dependent with the <code>fork</code> which creates that thread.</p></li>
<li><p>Unsynchronised writes are dependent with memory barriers.</p></li>
</ol>
<p>But are these <em>bugs</em>? I’m not so sure:</p>
<ol type="1">
<li><p>The dependency relation is only ever used to compare different threads.</p></li>
<li><p>This is technically correct, but it’s not interesting or useful.</p></li>
<li><p>This could be a bug. The relaxed memory implementation is pretty hairy and I’ve had a lot of problems with it in the past. Honestly, I just need to rewrite it (or campaign for Haskell to become sequentially consistent<a href="hedgehog-dejafu.html#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> and rip it out).</p></li>
</ol>
<p>But even if not bugs, these are definitely <em>confusing</em>. The dependency relation is currently just an internal thing, not exposed to users. However, I’m planning to expose a function to normalise traces, in which case providing an <code>independent</code> function is entirely reasonable.</p>
<p>So even if these changes don’t make it into <code>dependent</code>, they will be handled by <code>independent</code>.</p>
<p><strong>Next steps:</strong> I’m going to get this into the test suite, to get a large number of extra example programs for free. My hacky and cobbled-together testing framework in dejafu-tests is capable of running every test case with a variety of different schedulers, so I just need to add another way it runs everything. I won’t need to touch the actual tests, just the layer of glue which runs them all, which is nice.</p>
<p>The only problem is that this glue is currently based on <a href="https://hackage.haskell.org/package/HUnit">HUnit</a> and <a href="https://hackage.haskell.org/package/test-framework">test-framework</a>, whereas the only integration I can find for Hedgehog is <a href="https://hackage.haskell.org/package/tasty-hedgehog">tasty-hedgehog</a>, so I might need to switch to <a href="https://hackage.haskell.org/package/tasty">tasty</a> first. As usual, the hardest part is getting different libraries to co-operate!</p>
<p>Hopefully I’ll find some bugs! Well, not exactly <em>hopefully</em>, but you know what I mean.</p>
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1"><p>For all the gory details, see:</p>
<ul>
<li><p><strong>Dynamic partial order reduction for relaxed memory models</strong>, N. Zhang, M. Kusano, and C. Wang (2015)</p></li>
<li><p><strong>Bounded partial-order reduction</strong>, K. Coons, M. Musuvathi, and K. McKinley (2013)</p></li>
<li><p><strong>Refining dependencies improves partial-order verification methods</strong> (extended abstract), P. Godefroid and D. Pirottin (1993)</p></li>
</ul>
<a href="hedgehog-dejafu.html#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></li>
<li id="fn2"><p><strong>SC-Haskell: Sequential Consistency in Languages That Minimize Mutable Shared Heap</strong>, M. Vollmer, R. G. Scott, M. Musuvathi, and R. R. Newton (2017)<a href="hedgehog-dejafu.html#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>

      ]]>
    </summary>
  </entry>
  
  <entry>
    <title>100 Prisoners</title>
    <link href="https://memo.barrucadu.co.uk/100-prisoners.html" />
    <id>https://memo.barrucadu.co.uk/100-prisoners.html</id>
    <published>2017-11-01T00:00:00Z</published>
    <updated>2017-11-01T00:00:00Z</updated>
    <summary type="html">
      <![CDATA[
<p>There’s a popular logic puzzle which goes something like this:</p>
<blockquote>
There are 100 prisoners in solitary cells. There’s a central living room with one light bulb; this bulb is initially off. No prisoner can see the light bulb from his or her own cell. Everyday, the warden picks a prisoner equally at random, and that prisoner visits the living room. While there, the prisoner can toggle the bulb if he or she wishes. Also, the prisoner has the option of asserting that all 100 prisoners have been to the living room by now. If this assertion is false, all 100 prisoners are shot. However, if it is indeed true, all prisoners are set free and inducted into MENSA, since the world could always use more smart people. Thus, the assertion should only be made if the prisoner is 100% certain of its validity. The prisoners are allowed to get together one night in the courtyard, to discuss a plan. What plan should they agree on, so that eventually, someone will make a correct assertion?
</blockquote>
<p>We can express this as a concurrency problem: the warden is the scheduler, each prisoner is a thread, and when the program terminates every prisoner should have visited the living room.</p>
<p>Let’s set up some imports:</p>
<pre class="haskell literate"><code>{-# LANGUAGE RankNTypes #-}

import qualified Control.Concurrent.Classy as C
import           Control.Monad             (forever, when)
import           Data.Foldable             (for_)
import           Data.List                 (genericLength)
import           Data.Maybe                (mapMaybe)
import qualified Data.Set                  as S
import qualified Test.DejaFu               as D
import qualified Test.DejaFu.Common        as D
import qualified Test.DejaFu.SCT           as D</code></pre>
<h2 id="correctness">Correctness</h2>
<p>Before we try to implement a solution, let’s think about how we can check if an execution corresponds to the prisoners succeeding an entering MENSA, or failing and being shot.</p>
<p>Prisoners are threads, and the warden is the scheduler. So if every thread (prisoner) that is forked is scheduled (taken to the room), then the prisoners are successful:</p>
<pre class="haskell literate"><code>-- | Check if an execution corresponds to a correct guess.
isCorrect :: D.Trace -&gt; Bool
isCorrect trc = S.fromList (threads trc) == S.fromList (visits trc)

-- | Get all threads created.
threads :: D.Trace -&gt; [D.ThreadId]
threads trc = D.initialThread : mapMaybe go trc where
  go (_, _, D.Fork tid) = Just tid
  go _ = Nothing

-- | Get all scheduled threads
visits :: D.Trace -&gt; [D.ThreadId]
visits = mapMaybe go where
  go (D.Start    tid, _, _) = Just tid
  go (D.SwitchTo tid, _, _) = Just tid
  go _ = Nothing</code></pre>
<p>So now, given some way of setting up the game and running it to completion, we can test it and print some statistics:</p>
<pre class="haskell literate"><code>-- | Run the prison game and print statistics.
run :: D.Way -&gt; (forall m. C.MonadConc m =&gt; m ()) -&gt; IO ()
run way game = do
    traces &lt;- map snd &lt;$&gt; D.runSCT way D.defaultMemType game
    let successes = filter isCorrect traces
    let failures  = filter (not . isCorrect) traces
    putStrLn (show (length traces)    ++ &quot; total attempts&quot;)
    putStrLn (show (length successes) ++ &quot; successes&quot;)
    putStrLn (show (length failures)  ++ &quot; failures&quot;)
    putStrLn (show (avgvisits successes) ++ &quot; average number of room visits per success&quot;)
    putStrLn (show (avgvisits failures)  ++ &quot; average number of room visits per failure&quot;)
    putStrLn &quot;Sample sequences of visits:&quot;
    for_ (take 5 traces) (print . visits)
  where
    avgvisits ts = sum (map (fromIntegral . numvisits) ts) / genericLength ts
    numvisits = sum . map count where
      count (_, _, D.STM _ _) = 1
      count (_, _, D.BlockedSTM _) = 1
      count (_, _, D.Yield) = 1
      count _ = 0</code></pre>
<p>I have decided to assume that a prisoner will either yield (doing nothing) or perform some STM transaction while they’re in the room, to simplify things.</p>
<h2 id="the-perfect-solution">The Perfect Solution</h2>
<p>A slow but simple strategy is for the prisoners to nominate a leader. Only the leader can declare to the warden that everyone has visited the room. Whenever a prisoner other than the leader visits the room, if the light is <em>on</em>, they do nothing; otherwise, if this is their first time in the room with the light off, they turn it on, otherwise they leave it. Whenever the leader enters the room, they turn the light off. When the leader has turned the light off 99 times (or <code>1 - num_prisoners</code> times), they tell the warden that everyone has visited.</p>
<p>Let’s set up those algorithms:</p>
<pre class="haskell literate"><code>-- | The state of the light bulb.
data Light = IsOn | IsOff

-- | Count how many prisoners have toggled the light and terminate
-- when everyone has.
leader :: C.MonadConc m =&gt; Int -&gt; C.TVar (C.STM m) Light -&gt; m ()
leader prisoners light = go 0 where
  go counter = do
    counter&#39; &lt;- C.atomically $ do
      state &lt;- C.readTVar light
      case state of
        IsOn -&gt; do
          C.writeTVar light IsOff
          pure (counter + 1)
        IsOff -&gt; C.retry
    when (counter&#39; &lt; prisoners - 1)
      (go counter&#39;)

-- | Turn the light on once then do nothing.
notLeader :: C.MonadConc m =&gt; C.TVar (C.STM m) Light -&gt; m ()
notLeader light = do
  C.atomically $ do
    state &lt;- C.readTVar light
    case state of
      IsOn  -&gt; C.retry
      IsOff -&gt; C.writeTVar light IsOn
  forever C.yield</code></pre>
<p>So now we just need to create a program where the leader is the main thread and everyone else is a separate thread:</p>
<pre class="haskell literate"><code>-- | Most popular English male and female names, according to
-- Wikipedia.
name :: Int -&gt; String
name i = ns !! (i `mod` length ns) where
  ns = [&quot;Oliver&quot;, &quot;Olivia&quot;, &quot;George&quot;, &quot;Amelia&quot;, &quot;Harry&quot;, &quot;Emily&quot;]

-- | Set up the prison game.  The number of prisoners should be at
-- least 1.
prison :: C.MonadConc m =&gt; Int -&gt; m ()
prison prisoners = do
  light &lt;- C.atomically (C.newTVar IsOff)
  for_ [1..prisoners-1] (\i -&gt; C.forkN (name i) (notLeader light))
  leader prisoners light</code></pre>
<p>Because these are people, not just threads, I’ve given them names. The leader is just called “main” though, how unfortunate for them.</p>
<h3 id="testing">
Testing
</h3>
<p>Now we can try out our system and see if it works:</p>
<pre><code>λ&gt; let runS = run $ D.systematically (D.defaultBounds { D.boundPreemp = Nothing })
λ&gt; runS 1
1 total attempts
1 successes
0 failures
2.0 average number of room visits per success
NaN average number of room visits per failure
Sample sequences of visits:
[main]

λ&gt; runS 2
5 total attempts
5 successes
0 failures
7.0 average number of room visits per success
NaN average number of room visits per failure
Sample sequences of visits:
[main,Olivia,main,Olivia,main]
[main,Olivia,main,Olivia,main]
[main,Olivia,main,Olivia,main]
[main,Olivia,main,Olivia,main]
[main,Olivia,main]

λ&gt; runS 3
2035 total attempts
2035 successes
0 failures
133.39066339066338 average number of room visits per success
NaN average number of room visits per failure
Sample sequences of visits:
(big lists omitted)</code></pre>
<p>This doesn’t scale well. It’s actually a really bad case for concurrency testing: every thread is messing with the same shared state, so dejafu has to try all the orderings. Not good.</p>
<p>Taking another look at our prisoners, we can see two things which a human would use to decide whether some schedules are redundant or not:</p>
<ol type="1">
<li><p>If we adopt any schedule other than alternating leader / non-leader, threads will block without doing anything. So we should alternate.</p></li>
<li><p>When a non-leader has completed their task, they will always yield. So we should never schedule a prisoner who will yield.</p></li>
</ol>
<p>Unfortunately dejafu can’t really make use of (1). It could be inferred <em>if</em> dejafu was able to compare values inside <code>TVar</code>s, rather than just seeing that there had been a write. But Haskell doesn’t let us do that without slapping an <code>Eq</code> constraint on <code>writeTVar</code>, which I definitely don’t want to do (although maybe having a separate <code>eqwriteTVar</code>, <code>eqputMVar</code>, and so on would be a nice addition).</p>
<p>Fortunately, dejafu <em>can</em> do something with (2). It already bounds the maximum number of times a thread can yield, so that we can test constructs like spinlocks. This is called <em>fair bounding</em>. The default bound is 5, but if we set it to 0 dejafu will just never schedule a thread which is going to yield. Here we go:</p>
<pre><code>λ&gt; let runS = run $ D.systematically (D.defaultBounds { D.boundPreemp = Nothing, D.boundFair = Just 0 })
λ&gt; runS 1
1 total attempts
1 successes
0 failures
2.0 average number of room visits per success
NaN average number of room visits per failure
Sample sequences of visits:
[main]

λ&gt; runS 2
1 total attempts
1 successes
0 failures
4.0 average number of room visits per success
NaN average number of room visits per failure
Sample sequences of visits:
[main,Olivia,main]

λ&gt; runS 3
4 total attempts
4 successes
0 failures
7.5 average number of room visits per success
NaN average number of room visits per failure
Sample sequences of visits:
[main,Olivia,main,George,main]
[main,Olivia,George,main,George,main]
[main,George,main,Olivia,main]
[main,George,Olivia,main,Olivia,main]</code></pre>
<p>Much better! Although it still doesn’t scale as nicely as we’d like</p>
<pre><code>λ&gt; runS 4
48 total attempts
48 successes
0 failures
11.5 average number of room visits per success
NaN average number of room visits per failure
Sample sequences of visits:
[main,Olivia,main,George,main,Amelia,main]
[main,Olivia,main,George,Amelia,main,Amelia,main]
[main,Olivia,main,Amelia,main,George,main]
[main,Olivia,main,Amelia,George,main,George,main]
[main,Olivia,George,main,George,main,Amelia,main]

λ&gt; runS 5
1536 total attempts
1536 successes
0 failures
16.0 average number of room visits per success
NaN average number of room visits per failure
Sample sequences of visits:
[main,Olivia,main,George,main,Amelia,main,Harry,main]
[main,Olivia,main,George,main,Amelia,Harry,main,Harry,main]
[main,Olivia,main,George,main,Harry,main,Amelia,main]
[main,Olivia,main,George,main,Harry,Amelia,main,Amelia,main]
[main,Olivia,main,George,Amelia,main,Amelia,main,Harry,main]

λ&gt; runS 6
122880 total attempts
122880 successes
0 failures
21.0 average number of room visits per success
NaN average number of room visits per failure
Sample sequences of visits:
[main,Olivia,main,George,main,Amelia,main,Harry,main,Emily,main]
[main,Olivia,main,George,main,Amelia,main,Harry,Emily,main,Emily,main]
[main,Olivia,main,George,main,Amelia,main,Emily,main,Harry,main]
[main,Olivia,main,George,main,Amelia,main,Emily,Harry,main,Harry,main]
[main,Olivia,main,George,main,Amelia,Harry,main,Harry,main,Emily,main]</code></pre>
<p>The prisoners are stepping on each other’s toes and causing needless work. This is probably as good as we can do without adding some extra primitives to dejafu to optimise the case where we have an <code>Eq</code> instance available, unfortunately.</p>
<h3 id="a-silver-lining">
A Silver Lining
</h3>
<p>In concurrency testing terms, six threads is actually quite a lot.</p>
<p><a href="http://www.doc.ic.ac.uk/~afd/homepages/papers/pdfs/2014/PPoPP.pdf">Empirical studies</a> have found that many concurrency bugs can be exhibited with only two or three threads! Furthermore, most real-world concurrent programs don’t have every single thread operating on the same bit of shared state.</p>
<h2 id="the-good-enough-solution">The “Good-Enough” Solution</h2>
<p>There’s another school of thought which says to just wait for three years, because by then it’s very unlikely that any single prisoner had never visited the room. In fact, we would expect each prisoner to have been to the room ten times by then, assuming the warden is fair.</p>
<p>By keeping track of how many days have passed, we can try this out as well:</p>
<pre class="haskell literate"><code>leader :: C.MonadConc m =&gt; Int -&gt; C.TVar (C.STM m) Int -&gt; m ()
leader prisoners days = C.atomically $ do
  numDays &lt;- C.readTVar days
  C.check (numDays &gt;= (prisoners - 1) * 10)

notLeader :: C.MonadConc m =&gt; C.TVar (C.STM m) Int -&gt; m ()
notLeader days = forever . C.atomically $ C.modifyTVar days (+1)

prison :: C.MonadConc m =&gt; Int -&gt; m ()
prison prisoners = do
  days &lt;- C.atomically (C.newTVar 0)
  for_ [1..prisoners-1] (\i -&gt; C.forkN (name i) (notLeader days))
  leader prisoners days</code></pre>
<p>Now let’s see how these brave prisoners do (sample visit sequences omitted because they’re pretty long):</p>
<pre><code>λ&gt; let runR = run $ D.uniformly (R.mkStdGen 0) 100
λ&gt; runR 1
100 total attempts
100 successes
0 failures
2.0 average number of room visits per success
NaN average number of room visits per failure

λ&gt; runR 2
100 total attempts
100 successes
0 failures
18.35 average number of room visits per success
NaN average number of room visits per failure

λ&gt; runR 3
100 total attempts
100 successes
0 failures
31.92 average number of room visits per success
NaN average number of room visits per failure

λ&gt; runR 4
100 total attempts
100 successes
0 failures
43.52 average number of room visits per success
NaN average number of room visits per failure

λ&gt; runR 5
100 total attempts
100 successes
0 failures
55.88 average number of room visits per success
NaN average number of room visits per failure

λ&gt; runR 6
100 total attempts
100 successes
0 failures
67.37 average number of room visits per success
NaN average number of room visits per failure

λ&gt; runR 7
100 total attempts
100 successes
0 failures
77.05 average number of room visits per success
NaN average number of room visits per failure

λ&gt; runR 8
100 total attempts
99 successes
1 failures
90.4040404040404 average number of room visits per success
81.0 average number of room visits per failure

λ&gt; runR 9
100 total attempts
100 successes
0 failures
101.64 average number of room visits per success
NaN average number of room visits per failure

λ&gt; runR 10
100 total attempts
100 successes
0 failures
114.89 average number of room visits per success
NaN average number of room visits per failure</code></pre>
<p>Not bad at all! Although my puny VPS still can’t manage all 100.</p>

      ]]>
    </summary>
  </entry>
  
  <entry>
    <title>Writing a Concurrency Testing Library (Part 2): Exceptions</title>
    <link href="https://memo.barrucadu.co.uk/minifu-02.html" />
    <id>https://memo.barrucadu.co.uk/minifu-02.html</id>
    <published>2017-10-28T00:00:00Z</published>
    <updated>2017-10-28T00:00:00Z</updated>
    <summary type="html">
      <![CDATA[
<p>Welcome back to my series on implementing a concurrency testing library for Haskell. This is part 2 of the series, and today we’ll implement exceptions. If you missed part 1, you can read it <a href="minifu-01.html">here</a>.</p>
<p>As before, all code is available on <a href="https://github.com/barrucadu/minifu">GitHub</a>. The code for this post is under the “post-02” tag.</p>
<hr />
<p>Did you do last time’s homework task? It was to implement this interface:</p>
<pre class="haskell"><code>data CRef m a = -- ...

newCRef :: a -&gt; MiniFu m (CRef m a)

readCRef :: CRef m a -&gt; MiniFu m a

writeCRef :: CRef m a -&gt; a -&gt; MiniFu m ()

atomicModifyCRef :: CRef m a -&gt; (a -&gt; (a, b)) -&gt; MiniFu m b</code></pre>
<p>Here are my solutions, available at the “homework-01” tag:</p>
<ol type="1">
<li>(<a href="https://github.com/barrucadu/minifu/commit/2070bdfaf5174fc14f6835d8410988cf111a854a"><code>2070bdf</code></a>) Add the <code>CRef</code> type, the <code>PrimOp</code> constructors, and the wrapper functions</li>
<li>(<a href="https://github.com/barrucadu/minifu/commit/188eec562f619c26fe117dd891ff86befc27b5a2"><code>188eec5</code></a>) Implement the primops</li>
</ol>
<p>I also made some changes, available at the “pre-02” tag:</p>
<ol type="1">
<li>(<a href="https://github.com/barrucadu/minifu/commit/7ce6e41f8bdc60c73affa00f7760a46a7e6ecfc3"><code>7ce6e41</code></a>) Add a helper for primops which don’t create any identifiers</li>
<li>(<a href="https://github.com/barrucadu/minifu/commit/24197965787555c5552ce8cb70fcb078016a167c"><code>2419796</code></a>) Move some definitions into an internal module</li>
<li>(<a href="https://github.com/barrucadu/minifu/commit/9c49f9d76f27ce0fa1ed445c34d9107105e66171"><code>9c49f9d</code></a>) Change the type of the <code>block</code> helper to <code>MVarId -&gt; Threads m -&gt; Threads m</code></li>
<li>(<a href="https://github.com/barrucadu/minifu/commit/dabd84b1ed4f713889b607b142ecb2d1987ee804"><code>dabd84b</code></a>) Implement <code>readMVar</code></li>
</ol>
<p>Now on to the show…</p>
<h2 id="synchronous-exceptions">Synchronous exceptions</h2>
<p>We can’t implement exceptions with what we have already. We’re going to need some new primops. I think you’re getting a feel for how this works now, so I won’t drag this out. Here we go:</p>
<pre class="haskell"><code>import qualified Control.Exception as E

data PrimOp m where
  -- ...
  Throw :: E.Exception e =&gt; e -&gt; PrimOp m
  Catch :: E.Exception e =&gt; MiniFu m a -&gt; (e -&gt; MiniFu m a) -&gt; (a -&gt; PrimOp m)
        -&gt; PrimOp m
  PopH  :: PrimOp m -&gt; PrimOp m

throw :: E.Exception e =&gt; e -&gt; MiniFu m a
throw e = MiniFu (K.cont (\_ -&gt; Throw e))

catch :: E.Exception e =&gt; MiniFu m a -&gt; (e -&gt; MiniFu m a) -&gt; MiniFu m a
catch act h = MiniFu (K.cont (Catch act h))</code></pre>
<p>Throwing an exception with <code>throw</code> jumps back to the closest enclosing <code>catch</code> with an exception handler of the appropriate type, killing the thread if there is none. The <code>PopH</code> primop will pop the top exception handler from the stack. We’ll insert those as appropriate when entering a <code>catch</code>.</p>
<p>Before we can actually implement these primops, we need to give threads a place to store their exception handlers. You might have guessed it when I said “stack”: we’ll just give every thread a list of them. This requires changing our <code>Thread</code> type and <code>thread</code> function:</p>
<pre class="haskell"><code>data Thread m = Thread
  { threadK     :: PrimOp m
  , threadBlock :: Maybe MVarId
  , threadExc   :: [Handler m]                              -- &lt;- new
  }

data Handler m where
  Handler :: E.Exception e =&gt; (e -&gt; PrimOp m) -&gt; Handler m

thread :: PrimOp m -&gt; Thread m
thread k = Thread
  { threadK     = k
  , threadBlock = Nothing
  , threadExc   = []                                        -- &lt;- new
  }</code></pre>
<p>As <code>Exception</code> is a subclass of <code>Typeable</code>, given some exception value we’re able to look for the first matching handler:</p>
<pre class="haskell"><code>raise :: E.Exception e =&gt; e -&gt; Thread m -&gt; Maybe (Thread m)
raise exc thrd = go (threadExc thrd) where
  go (Handler h:hs) = case h &lt;$&gt; E.fromException exc&#39; of
    Just pop -&gt; Just (thrd { threadK = pop, threadBlock = Nothing, threadExc = hs })
    Nothing  -&gt; go hs
  go [] = Nothing

  exc&#39; = E.toException exc</code></pre>
<p>If <code>raise</code> returns a <code>Just</code>, then a handler was found and entered. Otherwise, no handler exists and the thread should be removed from the <code>Threads</code> collection. This can be expressed rather nicely as <code>M.update . raise</code>.</p>
<p>Now we have enough support to implement the primops:</p>
<pre class="haskell"><code>stepThread {- ... -}
  where
    -- ...
    go (Throw e) =
      simple (M.update (raise e) tid)
    go (Catch (MiniFu ma) h k) = simple . adjust $ \thrd -&gt; thrd
      { threadK   = K.runCont ma (PopH . k)
      , threadExc =
        let h&#39; exc = K.runCont (runMiniFu (h exc)) k
        in Handler h&#39; : threadExc thrd
      }
    go (PopH k) = simple . adjust $ \thrd -&gt; thrd
      { threadK   = k
      , threadExc = tail (threadExc thrd)
      }</code></pre>
<p>Let’s break that down:</p>
<ul>
<li><code>Throw</code> just re-uses our <code>raise</code> function to either jump to the exception handler or kill the thread.</li>
<li><code>Catch</code> changes the continuation of the thread to run the enclosed action, then do a <code>PopH</code> action, then run the outer action. It also adds an exception continuation, which just runs the exception handler, then runs the outer action.</li>
<li><code>PopH</code> just removes the head exception continuation.</li>
</ul>
<p>It’s important that the exception continuation <em>doesn’t</em> use <code>PopH</code> to remove itself: that happens in <code>raise</code> when an exception is thrown. When writing this section I realised I’d made that mistake in dejafu (<a href="https://github.com/barrucadu/dejafu/issues/139">#139</a>)!</p>
<h3 id="so-what">So what?</h3>
<p>So now we can use synchronous exceptions! Here’s an incredibly contrived example:</p>
<pre class="haskell"><code>{-# LANGUAGE ScopedTypeVariables #-}

import Control.Monad (join)

example_sync :: MiniFu m Int
example_sync = do
  a &lt;- newEmptyMVar
  fork (putMVar a (pure 1))
  fork (putMVar a (throw E.NonTermination))
  fork (putMVar a (throw E.AllocationLimitExceeded))
  catch
    (catch
      (join (readMVar a))
      (\(_ :: E.AllocationLimitExceeded) -&gt; pure 2))
    (\(_ :: E.NonTermination) -&gt; pure 3)

demo_sync :: IO ()
demo_sync = do
  g &lt;- R.newStdGen
  print . fst =&lt;&lt; minifu randomSched g example_sync</code></pre>
<p>If we run this a few times in ghci, we can see the different exceptions being thrown and caught (resulting in different outputs):</p>
<pre><code>λ&gt; demo_sync
Just 1
λ&gt; demo_sync
Just 3
λ&gt; demo_sync
Just 3
λ&gt; demo_sync
Just 2</code></pre>
<h3 id="monadthrow-and-monadcatch">MonadThrow and MonadCatch</h3>
<p><code>MonadConc</code> has a bunch of superclasses, and we can now implement two of them!</p>
<pre class="haskell"><code>import qualified Control.Monad.Catch as EM

instance EM.MonadThrow (MiniFu m) where
  throwM = -- &#39;throw&#39; from above

instance EM.MonadCatch (MiniFu m) where
  catch = -- &#39;catch&#39; from above</code></pre>
<p>The <a href="https://hackage.haskell.org/package/exceptions">exceptions</a> package provides the <code>MonadThrow</code>, <code>MonadCatch</code>, and <code>MonadMask</code> typeclasses, so we can talk about exceptions in a wider context than just <code>IO</code>. We’ll get on to <code>MonadMask</code> when we look at asynchronous exceptions.</p>
<h3 id="incompleteness">Incompleteness!</h3>
<p>It is with exceptions that we hit the first thing we can’t do in MiniFu.</p>
<p>When in <code>IO</code>, we can catch exceptions from pure code:</p>
<pre><code>λ&gt; import Control.Exception
λ&gt; evaluate undefined `catch` \e -&gt; putStrLn (&quot;Got &quot; ++ show (e :: SomeException))
Got Prelude.undefined
CallStack (from HasCallStack):
  error, called at libraries/base/GHC/Err.hs:79:14 in base:GHC.Err
  undefined, called at &lt;interactive&gt;:5:10 in interactive:Ghci2</code></pre>
<p>But we can’t do that in <code>MiniFu</code>, as there’s no suitable <code>evaluate</code> function.</p>
<p>Should there be an <code>evaluate</code> in the <code>MonadConc</code> class? I’m unconvinced, as it’s not really a <em>concurrency</em> operation.</p>
<p>Should we constrain the <code>m</code> in <code>MiniFu m</code> to be a <code>MonadIO</code>, which would let us call <code>evaluate</code>? Perhaps, that would certainly be a way to do it, and I’m currently investigating the advantages of an <code>IO</code> base monad for dejafu (although originally for a different reason).</p>
<h2 id="asynchronous-exceptions">Asynchronous exceptions</h2>
<p>Asynchronous exceptions are like synchronous exceptions, except for two details:</p>
<ol type="1">
<li>They are thrown to a thread identified by <code>ThreadId</code>. We can do this already with <code>raise</code>.</li>
<li>Raising the exception may be blocked due to the target thread’s <em>masking state</em>. We need to do some extra work to implement this.</li>
</ol>
<p>When a thread is masked, attempting to deliver an asynchronous exception to it will block. There are three masking states:</p>
<ul>
<li><code>Unmasked</code>, asynchronous exceptions are unmasked.</li>
<li><code>MaskedInterruptible</code>, asynchronous exceptions are masked, but blocked operations may still be interrupted.</li>
<li><code>MaskedUninterruptible</code>, asynchronous exceptions are masked, and blocked operations may not be interrupted.</li>
</ul>
<p>So we’ll add the current masking state to our <code>Thread</code> type, defaulting to <code>Unmasked</code>, and also account for blocking on another thread:</p>
<pre class="haskell"><code>data Thread m = Thread
  { threadK     :: PrimOp m
  , threadBlock :: Maybe (Either ThreadId MVarId)           -- &lt;- new
  , threadExc   :: [Handler m]
  , threadMask  :: E.MaskingState                           -- &lt;- new
  }

thread :: PrimOp m -&gt; Thread m
thread k = Thread
  { threadK     = k
  , threadBlock = Nothing
  , threadExc   = []
  , threadMask  = E.Unmasked                                -- &lt;- new
  }</code></pre>
<p>We’ll also need a primop to set the masking state:</p>
<pre class="haskell"><code>data PrimOp m where
  -- ...
  Mask :: E.MaskingState -&gt; PrimOp m -&gt; PrimOp m</code></pre>
<p>Which has a fairly straightforward implementation:</p>
<pre class="haskell"><code>stepThread {- ... -}
  where
    -- ...
    go (Mask ms k) = simple . adjust $ \thrd -&gt; thrd
      { threadK    = k
      , threadMask = ms
      }</code></pre>
<p>Finally, we need to make sure that if an exception is raised, and we jump into an exception handler, the masking state gets reset to what it was when the handler was created. This means we need a small change to the <code>Catch</code> primop:</p>
<pre class="haskell"><code>stepThread {- ... -}
  where
    -- ...
    go (Catch (MiniFu ma) h k) = simple . adjust $ \thrd -&gt; thrd
      { threadK   = K.runCont ma (PopH . k)
      , threadExc =
        let ms0 = threadMask thrd                           -- &lt;- new
            h&#39; exc = flip K.runCont k $ do
              K.cont (\c -&gt; Mask ms0 (c ()))                -- &lt;- new
              runMiniFu (h exc)
        in Handler h&#39; : threadExc thrd
      }</code></pre>
<p>Alright, now we have enough background to actually implement the user-facing operations.</p>
<h3 id="throwing">Throwing</h3>
<p>To throw an asynchronous exception, we’re going to need a new primop:</p>
<pre class="haskell"><code>data PrimOp m where
  -- ...
  ThrowTo :: E.Exception e =&gt; ThreadId -&gt; e -&gt; PrimOp m -&gt; PrimOp m</code></pre>
<p>Which has a corresponding wrapper function:</p>
<pre class="haskell"><code>throwTo :: E.Exception e =&gt; ThreadId -&gt; e -&gt; MiniFu m ()
throwTo tid e = MiniFu (K.cont (\k -&gt; ThrowTo tid e (k ())))</code></pre>
<p>Let’s think about the implementation of the <code>ThrowTo</code> primop. It first needs to check if the target thread is interruptible and, if so, raises the exception in that thread; if not, it blocks the current thread. A thread is interruptible if its masking state is <code>Unmasked</code>, or <code>MaskedInterruptible</code> and it’s currently blocked.</p>
<p>Let’s encapsulate that logic:</p>
<pre class="haskell"><code>import Data.Maybe (isJust)

isInterruptible :: Thread m -&gt; Bool
isInterruptible thrd =
  threadMask thrd == E.Unmasked ||
  (threadMask thrd == E.MaskedInterruptible &amp;&amp; isJust (threadBlock thrd))</code></pre>
<p>Given that, the implementation of <code>ThrowTo</code> is straightforward:</p>
<pre class="haskell"><code>stepThread {- ... -}
  where
    -- ...
    go (ThrowTo threadid e k) = simple $ case M.lookup threadid threads of
      Just t
        | isInterruptible t -&gt; goto k . M.update (raise e) threadid
        | otherwise         -&gt; block (Left threadid)
      Nothing -&gt; goto k</code></pre>
<p>First, check if the thread exists. Then check if it’s interruptible: if it is, raise the exception, otherwise block. If the thread doesn’t exist any more, just continue.</p>
<p>Now we just need to handle <em>unblocking</em> threads which are blocked in <code>ThrowTo</code>. For that, we’ll go back to the <code>run</code> function and add a pass to unblock threads if the current one is interruptible after it processes its action:</p>
<pre class="haskell"><code>run :: C.MonadConc m =&gt; Scheduler s -&gt; s -&gt; PrimOp m -&gt; m s
run sched s0 = go s0 . initialise where
  go s (threads, idsrc)
    | initialThreadId `M.member` threads = case runnable threads of
      Just tids -&gt; do
        let (chosen, s&#39;) = sched tids s
        (threads&#39;, idsrc&#39;) &lt;- stepThread chosen (threads, idsrc)
        let threads&#39;&#39; = if (isInterruptible &lt;$&gt; M.lookup chosen threads&#39;) /= Just False
                        then unblock (Left chosen) threads&#39;
                        else threads&#39;
            -- ^- new
        go s&#39; (threads&#39;&#39;, idsrc&#39;)
      Nothing -&gt; pure s
    | otherwise = pure s

  runnable = nonEmpty . M.keys . M.filter (isNothing . threadBlock)

  initialThreadId = fst (nextThreadId initialIdSource)</code></pre>
<p>So after stepping a thread, we unblock every thread blocked on it if it either doesn’t exist, of if it does exist and is interruptible. It’s much more robust to do this once here than everywhere in <code>stepThread</code> which might cause the thread to become interruptible.</p>
<h3 id="masking-and-monadmask">Masking and MonadMask</h3>
<p>There are two operations at the programmer’s disposal to change the masking state of a thread, <code>mask</code> and <code>uninterruptibleMask</code>. Here’s what the <code>MiniFu</code> types will look like:</p>
<pre class="haskell"><code>{-# LANGUAGE RankNTypes #-}

mask                :: ((forall x. MiniFu m x -&gt; MiniFu m x) -&gt; MiniFu m a) -&gt; MiniFu m a
uninterruptibleMask :: ((forall x. MiniFu m x -&gt; MiniFu m x) -&gt; MiniFu m a) -&gt; MiniFu m a</code></pre>
<p>Each takes an action to run, and runs it as either <code>MaskedInterruptible</code> or <code>MaskedUninterruptible</code>. The action is provided with a polymorphic callback to run a subcomputation with the original masking state.</p>
<p>This is going to need, you guessed it, a new primop! We <em>could</em> modify the <code>Mask</code> primop to do this job as well, but I think it’s a little clearer to have two separate ones:</p>
<pre class="haskell"><code>data PrimOp m where
  -- ...
  InMask :: E.MaskingState -&gt; ((forall x. MiniFu m x -&gt; MiniFu m x) -&gt; MiniFu m a)
         -&gt; (a -&gt; PrimOp m) -&gt; PrimOp m</code></pre>
<p>And here’s the implementations of our masking functions:</p>
<pre class="haskell"><code>mask ma = MiniFu (K.cont (InMask E.MaskedInterruptible ma))
uninterruptibleMask ma = MiniFu (K.cont (InMask E.MaskedUninterruptible ma))</code></pre>
<p>We can now fulfil another requirement of <code>MonadConc</code>: a <code>MonadMask</code> instance!</p>
<pre class="haskell"><code>instance MonadMask (MiniFu m) where
  mask = -- &#39;mask&#39; from above
  uninterruptibleMask = -- &#39;uninterruptibleMask&#39; from above</code></pre>
<p>The very last piece of the puzzle for exception handling in MiniFu is to implement this <code>InMask</code> primop. Its type looks quite intense, but the implementation is really not that bad. There are three parts:</p>
<pre class="haskell"><code>stepThread {- ... -}
  where
    -- ...
    go (InMask ms ma k) = simple . adjust $ \thrd -&gt; thrd
      { threadK =
        let ms0 = threadMask thrd

            -- (1) we need to construct the polymorphic argument function
            umask :: MiniFu m x -&gt; MiniFu m x
            umask (MiniFu mx) = MiniFu $ do
              K.cont (\c -&gt; Mask ms0 (c ()))
              x &lt;- mx
              K.cont (\c -&gt; Mask ms (c ()))
              pure x

        -- (2) we need to run the inner continuation, resetting the masking state
        -- when done
        in K.runCont (runMiniFu (ma umask)) (Mask ms0 . k)

      -- (3) we need to change the masking state
      , threadMask = ms
      }</code></pre>
<p>The explicit type signature on <code>umask</code> is needed because we’re using <code>GADTs</code>, which implies <code>MonoLocalBinds</code>, which prevents the polymorphic type from being inferred. We could achieve the same effect by turning on <code>NoMonoLocalBinds</code>.</p>
<h3 id="demo">Demo</h3>
<p>Now we have asynchronous exceptions, check it out:</p>
<pre class="haskell"><code>example_async :: MiniFu m String
example_async = do
  a &lt;- newEmptyMVar
  tid &lt;- fork (putMVar a &quot;hello from the other thread&quot;)
  throwTo tid E.ThreadKilled
  readMVar a

demo_async :: IO ()
demo_async = do
  g &lt;- R.newStdGen
  print . fst =&lt;&lt; minifu randomSched g example_async</code></pre>
<p>See:</p>
<pre><code>λ&gt; demo_async
Just &quot;hello from the other thread&quot;
λ&gt; demo_async
Just &quot;hello from the other thread&quot;
λ&gt; demo_async
Nothing</code></pre>
<h2 id="next-time">Next time…</h2>
<p>We have come to the end of part 2! Again, I hope you enjoyed this post, any feedback is welcome. This is all on <a href="https://github.com/barrucadu/minifu">GitHub</a>, and you can see the code we ended up with at the “post-02” tag.</p>
<p>Once again, I have some homework for you. Your task, should you choose to accept it, is to implement:</p>
<pre class="haskell"><code>tryPutMVar :: MVar m a -&gt; a -&gt; MiniFu m Bool

tryTakeMVar :: MVar m a -&gt; MiniFu m (Maybe a)

tryReadMVar :: MVar m a -&gt; MiniFu m (Maybe a)</code></pre>
<p>Solutions will be up in a few days, as before, at the “homework-02” tag.</p>
<p>Stay tuned because next time we’re going to implement STM: all of it in one go. Then we can finally get on to the testing.</p>
<hr />
<p>Thanks to <a href="https://twitter.com/willsewell_">Will Sewell</a> for reading an earlier draft of this post.</p>

      ]]>
    </summary>
  </entry>
  
  <entry>
    <title>Writing a Concurrency Testing Library (Part 1)</title>
    <link href="https://memo.barrucadu.co.uk/minifu-01.html" />
    <id>https://memo.barrucadu.co.uk/minifu-01.html</id>
    <published>2017-10-14T00:00:00Z</published>
    <updated>2017-10-14T00:00:00Z</updated>
    <summary type="html">
      <![CDATA[
<p>Welcome to the first part of a tutorial on writing your very own concurrency testing library for Haskell. Before we get into the details, let’s just clarify what I mean by a “concurrency testing library”. The goal is a function which, given some concurrent Haskell like so:</p>
<pre class="haskell"><code>example = do
  a &lt;- newEmptyMVar
  forkIO (putMVar a 1)
  forkIO (putMVar a 2)
  takeMVar a</code></pre>
<p>Will tell us the possible results of that computation:</p>
<pre><code>λ&gt; test example
[1, 2]</code></pre>
<p>We’re going to build this from the ground up, using the <a href="https://hackage.haskell.org/package/concurrency">concurrency</a> library, as it provides a typeclass abstraction over forking, MVars, STM, and suchlike.</p>
<p>You may have come across my <a href="https://hackage.haskell.org/package/dejafu">dejafu</a> library before. If not, don’t worry, but you may want to check it out as we’re going to be building something very similar.</p>
<h2 id="lets-get-down-to-business">Let’s get down to business</h2>
<p>Ok, with the preliminaries over, let’s get coding! All the code written in this series is on <a href="https://github.com/barrucadu/minifu">GitHub</a>, with one tag for each post. The code for this post is under the “post-01” tag.</p>
<p>The goal in this post is to be able to implement a function which can execute simple thread-and-MVar computations (like the example from the beginning) with a stateful scheduler. Firstly, let’s say what we know:</p>
<ul>
<li>We’re using the <code>MonadConc</code> typeclass from <a href="https://hackage.haskell.org/package/concurrency">concurrency</a>, rather than <code>IO</code>.</li>
<li>We want to be able to examine arbitrary <code>MonadConc</code> computations.</li>
<li>We also want to be able to pause and resume “threads” at will, so we can explore different executions.</li>
</ul>
<p>That sounds rather like something based on continuations or a free monad. Furthermore, we’re going to need mutable state to implement all of this, as we’re modelling a DSL with mutable references, and doing that purely is a huge pain.</p>
<p>Let’s write down some types. Because we’re writing a mini-dejafu, I’m calling this project “minifu”. So we want a function:</p>
<pre class="haskell"><code>import qualified Control.Concurrent.Classy as C
import Data.List.NonEmpty (NonEmpty(..))

newtype ThreadId = ThreadId Int
  deriving (Eq, Ord)

type Scheduler s = NonEmpty ThreadId -&gt; s -&gt; (ThreadId, s)

minifu :: C.MonadConc m =&gt; Scheduler s -&gt; s -&gt; MiniFu m a -&gt; m (Maybe a, s)</code></pre>
<p>For some suitable <code>MiniFu</code> monad transformer. Now we’re going to take the standard way of constructing a free monad, and have a data structure representing our class of interest (<code>MonadConc</code>), with one constructor for every function. Because we’re only talking about threads and MVars in this post, it will be a fairly small type:</p>
<pre class="haskell"><code>{-# LANGUAGE GADTs #-}

data PrimOp m where
  Fork         :: MiniFu m () -&gt; (ThreadId -&gt; PrimOp m) -&gt; PrimOp m
  NewEmptyMVar :: (MVar m a -&gt; PrimOp m)                -&gt; PrimOp m
  PutMVar      :: MVar m a -&gt; a -&gt; PrimOp m             -&gt; PrimOp m
  TakeMVar     :: MVar m a -&gt; (a -&gt; PrimOp m)           -&gt; PrimOp m
  Stop         :: m ()                                  -&gt; PrimOp m

newtype MVarId = MVarId Int
  deriving (Eq, Ord)

data MVar m a = MVar
  { mvarId  :: MVarId
  , mvarRef :: C.CRef m (Maybe a)
  }</code></pre>
<p>The <code>Stop</code> action is what is going to let us communicate the final result out of the computation. I’ve also defined an <code>MVar</code> type. Our MVars are going to be implemented as a <code>CRef</code> (what <a href="https://hackage.haskell.org/package/concurrency">concurrency</a> calls an <code>IORef</code>) holding a maybe value, along with an identifier. These identifiers will come into play when we look at threads blocking.</p>
<p>Given this set up, the <code>MiniFu</code> type is very simple:</p>
<pre class="haskell"><code>{-# LANGUAGE GeneralizedNewtypeDeriving #-}

import qualified Control.Monad.Cont as K

newtype MiniFu m a = MiniFu { runMiniFu :: K.Cont (PrimOp m) a }
  deriving (Functor, Applicative, Monad)</code></pre>
<p>We’re not actually going to write a <code>MonadConc</code> instance for <code>MiniFu</code> yet, because there are a bunch of constraints which we can’t really satisfy. But we can still define the functions of interest:</p>
<pre class="haskell"><code>fork :: MiniFu m () -&gt; MiniFu m ThreadId
fork ma = MiniFu (K.cont (Fork ma))

newEmptyMVar :: MiniFu m (MVar m a)
newEmptyMVar = MiniFu (K.cont NewEmptyMVar)

putMVar :: MVar m a -&gt; a -&gt; MiniFu m ()
putMVar v a = MiniFu (K.cont (\k -&gt; PutMVar v a (k ())))

takeMVar :: MVar m a -&gt; MiniFu m a
takeMVar v = MiniFu (K.cont (TakeMVar v))</code></pre>
<p>Hey, not bad! Now we can slap a <code>MiniFu m Int</code> type signature on our example from the start (and rename the <code>forkIO</code> calls) and it compiles!</p>
<pre class="haskell"><code>example :: MiniFu m Int
example = do
  a &lt;- newEmptyMVar
  fork (putMVar a 1)
  fork (putMVar a 2)
  takeMVar a</code></pre>
<p>Take a moment to make sure you’re happy with this section before moving on to the next. MiniFu is going to be a layered application: this is the basic layer which defines the functions we can test; the next layer executes a MiniFu computation; the layers above that will implement the systematic testing behaviour.</p>
<h2 id="implementing-minifu">Implementing <code>minifu</code></h2>
<p>Recall the type of <code>minifu</code>:</p>
<pre class="haskell"><code>minifu :: C.MonadConc m =&gt; Scheduler s -&gt; s -&gt; MiniFu m a -&gt; m (Maybe a, s)</code></pre>
<p>So, what does it need to do? It needs to set up the execution environment: in this case that’s specifying that the provided computation is the main thread, and then it needs to repeatedly call the scheduler, executing one <code>PrimOp</code> of the chosen thread at a time, until either the main thread terminates or everything is blocked.</p>
<p>In the best functional programming practice, <code>minifu</code> is going to do the minimum it can and call another function to do the rest. So what <code>minifu</code> is <em>actually</em> going to do is to extract the continuation and set up the mechanism to communicate the final result back:</p>
<pre class="haskell"><code>minifu sched s (MiniFu ma) = do
  out &lt;- C.newCRef Nothing
  s&#39;  &lt;- run sched s (K.runCont ma (Stop . C.writeCRef out . Just))
  a   &lt;- C.readCRef out
  pure (a, s&#39;)</code></pre>
<p>Before we move on to the implementation of <code>run</code>, let’s first look at two concerns we’ll have along the way: getting unique names (for threads and MVars) and representing threads.</p>
<h3 id="names">Names</h3>
<p>Each thread gets a unique <code>ThreadId</code>, and each MVar gets a unique <code>MVarId</code>. As these are just an <code>Int</code>, we can use the same source for both:</p>
<pre class="haskell"><code>type IdSource = Int

initialIdSource :: IdSource
initialIdSource = 0

nextThreadId :: IdSource -&gt; (ThreadId, IdSource)
nextThreadId n = (ThreadId n, n + 1)

nextMVarId :: IdSource -&gt; (MVarId, IdSource)
nextMVarId n = (MVarId n, n + 1)</code></pre>
<p>This is as simple as it gets, but it’s good enough for now.</p>
<h3 id="threads">Threads</h3>
<p>What is a thread? Well, it has a continuation, which is some value of type <code>PrimOp m</code>, and it might be blocked. We want to know if a thread is blocked for two reasons: we don’t want the scheduler to schedule a blocked thread, and we want to be able to tell if the computation is deadlocked. Threads can only block on reading from or writing to MVars (currently), so let’s use a <code>Maybe MVarId</code> to indicate whether the thread is blocked:</p>
<pre class="haskell"><code>data Thread m = Thread
  { threadK     :: PrimOp m
  , threadBlock :: Maybe MVarId
  }</code></pre>
<p>When we create a thread, it’s initially unblocked:</p>
<pre class="haskell"><code>thread :: PrimOp m -&gt; Thread m
thread k = Thread
  { threadK     = k
  , threadBlock = Nothing
  }</code></pre>
<p>And finally we need a way to construct our initial collection of threads:</p>
<pre class="haskell"><code>import Data.Map (Map)
import qualified Data.Map as M

type Threads m = Map ThreadId (Thread m)

initialise :: PrimOp m -&gt; (Threads m, IdSource)
initialise k =
  let (tid, idsrc) = nextThreadId initialIdSource
  in (M.singleton tid (thread k), idsrc)</code></pre>
<p>And now back to the implementation of <code>minifu</code>.</p>
<h3 id="implementing-run">Implementing <code>run</code></h3>
<p>The <code>run</code> function is responsible for taking the first continuation, creating the collection of threads, and repeatedly calling the scheduler and stepping the chosen thread, until the computation is done.</p>
<p>It has this type:</p>
<pre class="haskell"><code>run :: C.MonadConc m =&gt; Scheduler s -&gt; s -&gt; PrimOp m -&gt; m s</code></pre>
<p>As with <code>minifu</code>, we shall keep it simple, and delegate most of the work to yet another function:</p>
<pre class="haskell"><code>import Data.List.NonEmpty (nonEmpty)
import Data.Maybe (isNothing)

run sched s0 = go s0 . initialise where
  go s (threads, ids)
    | initialThreadId `M.member` threads = case runnable threads of
      Just tids -&gt;
        let (chosen, s&#39;) = sched tids s
        in go s&#39; =&lt;&lt; stepThread chosen (threads, ids)
      Nothing -&gt; pure s
    | otherwise = pure s

  runnable = nonEmpty . M.keys . M.filter (isNothing . threadBlock)

  initialThreadId = fst (nextThreadId initialIdSource)</code></pre>
<p>Let’s break down that <code>go</code> function a bit:</p>
<ol type="1">
<li>We check if the initial thread still exists. If not, we return.</li>
<li>We check if the collection of runnable threads is nonempty. If not, we return.</li>
<li>We call the scheduler to pick a thread from the runnable ones.</li>
<li>We call the (not yet defined) <code>stepThread</code> function to execute one step of that thread.</li>
<li>We go around the loop again.</li>
</ol>
<p>Not too bad, hey? Finally (really finally) we just have one function to go, <code>stepThread</code>. Can you see what the type will be?</p>
<p>It’s going to start like this:</p>
<pre class="haskell"><code>stepThread :: C.MonadConc m =&gt; ThreadId -&gt; (Threads m, IdSource) -&gt; m (Threads m, IdSource)
stepThread tid (threads, idsrc) = case M.lookup tid threads of
    Just thrd -&gt; go (threadK thrd)
    Nothing -&gt; pure (threads, idsrc)
  where
    adjust :: (Thread m -&gt; Thread m) -&gt; Threads m -&gt; Threads m
    adjust f = M.adjust f tid

    goto :: PrimOp m -&gt; Threads m -&gt; Threads m
    goto k = adjust (\thrd -&gt; thrd { threadK = k })

    block :: Maybe MVarId -&gt; Threads m -&gt; Threads m
    block mv = adjust (\thrd -&gt; thrd { threadBlock = mv })

    unblock :: MVarId -&gt; Threads m -&gt; Threads m
    unblock v = fmap (\thrd -&gt;
      if threadBlock thrd == Just v
      then thrd { threadBlock = Nothing }
      else thrd)

    go :: PrimOp m -&gt; m (Threads m, IdSource)
    -- go ...</code></pre>
<p>I’ve introduced a few helper functions, which will crop up a lot. That <code>go</code> function will have a case for every constructor of <code>PrimOp m</code>, and it’s going to look a bit hairy, so we’ll take it one constructor at a time. Let’s do the constructors in order.</p>
<p>First, we can fork threads:</p>
<pre class="haskell"><code>    go (Fork (MiniFu ma) k) =
      let (tid&#39;, idsrc&#39;) = nextThreadId idsrc
          thrd&#39; = thread (K.runCont ma (\_ -&gt; Stop (pure ())))
      in pure (goto (k tid&#39;) (M.insert tid&#39; thrd&#39; threads), idsrc&#39;)</code></pre>
<p>Forking is pretty straightforward. We simply get the next available <code>ThreadId</code> from the <code>IdSource</code>, create a thread with the provided continuation, and insert it into the <code>Threads m</code> map.</p>
<p>Next up is <code>NewEmptyMVar</code>:</p>
<pre class="haskell"><code>    go (NewEmptyMVar k) = do
      ref &lt;- C.newCRef Nothing
      let (mvid, idsrc&#39;) = nextMVarId idsrc
      pure (goto (k (MVar mvid ref)) threads, idsrc&#39;)</code></pre>
<p>Remember that we’re implementing our <code>MVar</code> type using the <code>CRef</code> type of the underlying <code>MonadConc</code>. As the <code>MVar</code> starts out empty, the <code>CRef</code> starts out holding <code>Nothing</code>.</p>
<p>The <code>PutMVar</code> and <code>TakeMVar</code> actions are almost the same, so let’s tackle them together:</p>
<pre class="haskell"><code>    go (PutMVar (MVar mvid ref) a k) = do
      old &lt;- C.readCRef ref
      case old of
        Just _ -&gt; pure (block (Just mvid) threads, idsrc)
        Nothing -&gt; do
          C.writeCRef ref (Just a)
          pure (goto k (unblock mvid threads), idsrc)

    go (TakeMVar (MVar mvid ref) k) = do
      old &lt;- C.readCRef ref
      case old of
        Just a -&gt; do
          C.writeCRef ref Nothing
          pure (goto (k a) (unblock mvid threads), idsrc)
        Nothing -&gt; pure (block (Just mvid) threads, idsrc)</code></pre>
<p>In both cases, we start out by reading the value of the reference. Remember that <code>Nothing</code> indicates emptiness, and <code>Just</code> indicates the presence of a value. So, for <code>PutMVar</code> <em>if there already is a value</em> (and for <code>TakeMVar</code> <em>if there isn’t a value</em>), we block the thread. In the other case, we update the value in the reference, putting in the new value (or taking out the old), unblock all the relevant threads, and go to the continuation.</p>
<p>These implementations are not atomic. But that’s fine: despite MiniFu testing concurrent programs, there’s no concurrency going on within MiniFu itself. We can do as much or as little as we want during one atomic “step” of our program. This will turn out to be very useful when we implement STM in a few posts time.</p>
<p>Finally, we have <code>Stop</code>:</p>
<pre class="haskell"><code>    go (Stop mx) = do
      mx
      pure (M.delete tid threads, idsrc)</code></pre>
<p>And we’re done! That’s it! All we need now is a scheduler, and we can execute our example!</p>
<h2 id="a-simple-scheduler">A Simple Scheduler</h2>
<p>Our example is nondeterministic, so we want a scheduler which will let us see that. It would be no good us implementing something which always made the same decisions, as we’d only see one result! So until we implement the systematic testing behaviour, let’s just use a simple random scheduler.</p>
<pre class="haskell"><code>import qualified System.Random as R

randomSched :: R.RandomGen g =&gt; Scheduler g
randomSched (t:|ts) g =
  let (i, g&#39;) = R.randomR (0, length ts) g
  in ((t:ts) !! i, g&#39;)</code></pre>
<p>There’s no deep magic here, we’re just picking a random value from a nonempty list. Finally, we can construct a little demo:</p>
<pre class="haskell"><code>demo :: IO ()
demo = do
  g &lt;- R.newStdGen
  print . fst =&lt;&lt; minifu randomSched g example</code></pre>
<p>Which we can run in ghci like so:</p>
<pre><code>λ&gt; demo
Just 1
λ&gt; demo
Just 1
λ&gt; demo
Just 1
λ&gt; demo
Just 2
λ&gt; demo
Just 1</code></pre>
<p>Success!</p>
<p>A random scheduler is fine for demonstration purposes, but not so great for testing. Different seeds may lead to the same execution, which makes it hard to know how many executions of a test is enough. It can be a useful technique, but for us this is only the beginning.</p>
<h2 id="next-time">Next time…</h2>
<p>Next time we’ll look at implementing exceptions, both synchronous and asynchronous.</p>
<p>I hope you enjoyed this post, any feedback is welcome. As I mentioned at the start, this is on <a href="https://github.com/barrucadu/minifu">GitHub</a>, you can get the code we ended up with at the “post-01” tag.</p>
<p><em>Before</em> next time, I have some homework for you! You have seen how to implement MVars, so now try implementing CRefs! Here are the functions should you have a go at writing:</p>
<pre class="haskell"><code>data CRef m a = -- ...

newCRef :: a -&gt; MiniFu m (CRef m a)

readCRef :: CRef m a -&gt; MiniFu m a

writeCRef :: CRef m a -&gt; a -&gt; MiniFu m ()

atomicModifyCRef :: CRef m a -&gt; (a -&gt; (a, b)) -&gt; MiniFu m b</code></pre>
<p>Don’t worry about any of the relaxed memory stuff implemented in dejafu, just do sequential consistency (and if you don’t know what that means: it means to do the obvious). I’ll put up a solution (and maybe do a little refactoring) before the next post.</p>
<hr />
<p>Thanks to <a href="https://twitter.com/josecalderon">José Manuel Calderón Trilla</a> for reading an earlier draft of this post.</p>

      ]]>
    </summary>
  </entry>
  
  <entry>
    <title>A Multithreaded Runtime for Deja Fu</title>
    <link href="https://memo.barrucadu.co.uk/dejafu-multithreaded-runtime.html" />
    <id>https://memo.barrucadu.co.uk/dejafu-multithreaded-runtime.html</id>
    <published>2017-10-03T00:00:00Z</published>
    <updated>2017-10-03T00:00:00Z</updated>
    <summary type="html">
      <![CDATA[
<p>The dejafu situation currently looks something like this:</p>
<ol type="1">
<li><p>We have a <em>typeclass</em> abstracting over concurrency.</p>
<ul>
<li>There’s an implementation of this typeclass using <code>IO</code>.</li>
<li>There’s also an implementation of this typeclass using a custom monad transformer called <code>ConcT</code>.</li>
</ul></li>
<li><p>Computations of type <code>MonadRef r n =&gt; ConcT r n a</code> can be executed with a given scheduler, to produce a result and an execution trace.</p></li>
<li><p>Unlike <code>IO</code>, the threads in a <code>ConcT r n</code> computation are executed in a single-step fashion based on the decisions of the scheduler.</p></li>
<li><p>To implement this single-step execution, all threads are executed in a single “real” thread.</p></li>
</ol>
<p>It’s the third point that gives dejafu the ability to systematically explore different executions. If execution were not single-step, then it wouldn’t be possible in general to context switch between arbitrary concurrency actions.</p>
<p>The fourth point greatly simplifies the implementation, but also causes problems: GHC Haskell has a notion of “bound threads”, which are Haskell threads bound to a particular OS thread. Bound threads are absolutely essential to use FFI calls which rely on thread-local state. <strong>Deja Fu cannot support bound threads if it executes everything in a single thread!</strong></p>
<p>How can we address this?</p>
<h2 id="pulse">PULSE</h2>
<p><a href="http://www.cse.chalmers.se/~nicsma/papers/finding-race-conditions.pdf">PULSE</a> is a concurrency-testing tool for Erlang. It works by code instrumentation: around every communication operation is inserted a call to the PULSE scheduler process. The scheduler process tells processes when they can run. Execution is <em>not</em> serialised into a single thread, the distinct Erlang processes still exist, but only one of them may run at a time.</p>
<p>We can do the same thing in Haskell.</p>
<h2 id="mini-fu">Mini Fu</h2>
<p>Let’s look at a much simplified version of dejafu to try this idea out.</p>
<pre class="haskell literate"><code>{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE TypeFamilies #-}

import qualified Control.Concurrent as C
import qualified Control.Monad.Cont as K
import Data.List.NonEmpty (NonEmpty(..), nonEmpty)
import qualified Data.Map as M
import Data.Maybe (isNothing)
import qualified System.Random as R

class Monad m =&gt; MonadConc m where
  type ThreadId m :: *
  type MVar     m :: * -&gt; *

  fork   :: m () -&gt; m (ThreadId m)
  forkOS :: m () -&gt; m (ThreadId m)

  newEmptyMVar :: m (MVar m a)
  putMVar  :: MVar m a -&gt; a -&gt; m ()
  takeMVar :: MVar m a -&gt; m a

newMVar :: MonadConc m =&gt; a -&gt; m (MVar m a)
newMVar a = do
  v &lt;- newEmptyMVar
  putMVar v a
  pure v</code></pre>
<p>There’s a straightforward implementation for <code>IO</code>:</p>
<pre class="haskell literate"><code>instance MonadConc IO where
  type ThreadId IO = C.ThreadId
  type MVar     IO = C.MVar

  fork   = C.forkIO
  forkOS = C.forkOS

  newEmptyMVar = C.newEmptyMVar
  putMVar  = C.putMVar
  takeMVar = C.takeMVar</code></pre>
<p>The testing implementation is a little hairier. Because we want to be able to single-step it, we’ll use continuations:</p>
<pre class="haskell literate"><code>newtype ConcT m a = ConcT { runConcT :: K.Cont (Action m) a }
  deriving (Functor, Applicative, Monad)

newtype CTThreadId = CTThreadId Int
  deriving (Eq, Ord)

data CTMVar m a = CTMVar { mvarID :: Int, mvarRef :: MVar m (Maybe a) }

data Action m
  = Fork   (ConcT m ()) (CTThreadId -&gt; Action m)
  | ForkOS (ConcT m ()) (CTThreadId -&gt; Action m)
  | forall a. NewEmptyMVar (CTMVar m a -&gt; Action m)
  | forall a. PutMVar  (CTMVar m a) a (Action m)
  | forall a. TakeMVar (CTMVar m a)   (a -&gt; Action m)
  | Stop (m ())

instance MonadConc (ConcT m) where
  type ThreadId (ConcT m) = CTThreadId
  type MVar     (ConcT m) = CTMVar m

  fork   ma = ConcT (K.cont (Fork   ma))
  forkOS ma = ConcT (K.cont (ForkOS ma))

  newEmptyMVar = ConcT (K.cont NewEmptyMVar)
  putMVar  mvar a = ConcT (K.cont (\k -&gt; PutMVar mvar a (k ())))
  takeMVar mvar   = ConcT (K.cont (TakeMVar mvar))</code></pre>
<p>Let’s talk about the <code>Action</code> type a bit before moving on. The general structure is <code>Name [&lt;args&gt; ...] (&lt;result&gt; -&gt; Action m)</code>, where <code>m</code> is some <code>MonadConc</code>. For <code>MVar</code>s, we’re just re-using the <code>MVar</code> type of the underlying monad (dejafu proper re-uses the <code>IORef</code>s of the underlying monad). For <code>ThreadId</code>s we’re using <code>Int</code>s. And we’re going to get the final result out of the computation with the <code>Stop</code> action.</p>
<h2 id="implementing-mini-fu">Implementing Mini Fu</h2>
<p>Let’s keep things simple and not support most of the fancy scheduling stuff dejafu does. Our scheduler is just going to be a stateful function from runnable threads to a single thread:</p>
<pre class="haskell literate"><code>type Scheduler s = NonEmpty CTThreadId -&gt; s -&gt; (CTThreadId, s)</code></pre>
<p>So now our execution function is going to look like this:</p>
<pre class="haskell literate"><code>minifu :: MonadConc m =&gt; Scheduler s -&gt; s -&gt; ConcT m a -&gt; m (Maybe a, s)
minifu sched s (ConcT ma) = do
  out &lt;- newMVar Nothing
  s&#39;  &lt;- run sched s (K.runCont ma (\a -&gt; Stop (takeMVar out &gt;&gt; putMVar out (Just a))))
  a   &lt;- takeMVar out
  pure (a, s&#39;)</code></pre>
<p>The real meat is the <code>run</code> function:</p>
<pre class="haskell literate"><code>run :: MonadConc m =&gt; Scheduler s -&gt; s -&gt; Action m -&gt; m s
run sched s0 a0 = go s0 initialIdSource =&lt;&lt; initialThreads a0 where
  go s ids threads
    | initialThreadId `M.member` threads = case runnable threads of
      Just tids -&gt;
        let (chosen, s&#39;) = sched tids s
        in uncurry (go s&#39;) =&lt;&lt; loopStepThread ids chosen threads
      Nothing -&gt; pure s
    | otherwise = pure s

  runnable = nonEmpty . M.keys . M.filter (isNothing . blockedOn)</code></pre>
<p>Like in dejafu proper, execution is going to if the main thread terminates, even if there are other threads. Threads are going to live in a map keyed by <code>ThreadId</code>.</p>
<pre class="haskell literate"><code>type Threads m = M.Map CTThreadId (Thread m)

initialThreads :: MonadConc m =&gt; Action m -&gt; m (Threads m)
initialThreads a0 = do
  t &lt;- forkThread False a0
  pure (M.singleton initialThreadId t)

initialThreadId :: CTThreadId
initialThreadId = CTThreadId 0</code></pre>
<p>Each thread in our program-under-test is going to be executed in an actual thread. So, like PULSE, we’ll introduce communication (in the form of <code>MVar</code>s) around concurrency actions to ensure that we get single-step execution. So a thread is going to have three components: the <code>MVar</code> (if any) it’s currently blocked on, an <code>MVar</code> to signal that it should execute one step, and an <code>MVar</code> to communicate what the thread did.</p>
<pre class="haskell literate"><code>data Thread m = Thread
  { blockedOn   :: Maybe Int
  , signalStep  :: MVar m IdSource
  , awaitResult :: MVar m (IdSource, ThreadResult m)
  }

data ThreadResult m
  = BusinessAsUsual
  | Killed
  | Updated Int
  | Blocked Int
  | Forked (Thread m)</code></pre>
<p>The <code>IdSource</code> is used to generate new unique thread and <code>MVar</code> IDs:</p>
<pre class="haskell literate"><code>type IdSource = (Int, Int)

initialIdSource :: IdSource
initialIdSource = (1, 0)

nextThreadId :: IdSource -&gt; (CTThreadId, IdSource)
nextThreadId (t, m) = (CTThreadId t, (t + 1, m))

nextMVarId :: IdSource -&gt; (Int, IdSource)
nextMVarId (t, m) = (m, (t, m + 1))</code></pre>
<p>Forking a thread is going to set up these <code>MVar</code>s and the small bit of logic to ensure things happen as we like:</p>
<pre class="haskell literate"><code>forkThread :: MonadConc m =&gt; Bool -&gt; Action m -&gt; m (Thread m)
forkThread isOS act = do
  signal &lt;- newEmptyMVar
  await  &lt;- newEmptyMVar
  _ &lt;- (if isOS then forkOS else fork) (runThread signal await act)
  pure (Thread Nothing signal await)

runThread :: MonadConc m =&gt; MVar m IdSource -&gt; MVar m (IdSource, ThreadResult m) -&gt; Action m -&gt; m ()
runThread signal await = go where
  go act = do
    ids &lt;- takeMVar signal
    (act&#39;, ids&#39;, res) &lt;- runStepThread ids act
    putMVar await (ids&#39;, res)
    maybe (pure ()) go act&#39;</code></pre>
<p>The final pieces of the puzzle are the two <code>*StepThread</code> functions, which executes one action of our chosen thread. These are a little tricker than in normal dejafu.</p>
<p>Firstly, <code>loopStepThread</code>, which tells the thread that was chosen by the scheduler to step:</p>
<pre class="haskell literate"><code>loopStepThread :: MonadConc m =&gt; IdSource -&gt; CTThreadId -&gt; Threads m -&gt; m (IdSource, Threads m)
loopStepThread ids tid threads = case M.lookup tid threads of
  Just thread -&gt; do
    putMVar (signalStep thread) ids
    (ids&#39;, res) &lt;- takeMVar (awaitResult thread)
    let resf = case res of
          BusinessAsUsual -&gt; id
          Killed -&gt; M.delete tid
          Updated i -&gt; fmap (\t -&gt; if blockedOn t == Just i then t { blockedOn = Nothing } else t)
          Blocked i -&gt; M.insert tid (thread { blockedOn = Just i })
          Forked thread&#39; -&gt; M.insert (fst (nextThreadId ids)) thread&#39;
    pure (ids&#39;, resf threads)
  Nothing -&gt; pure (ids, threads)</code></pre>
<p>Finally <code>runStepThread</code>, which executes an action:</p>
<pre class="haskell literate"><code>runStepThread :: MonadConc m =&gt; IdSource -&gt; Action m -&gt; m (Maybe (Action m), IdSource, ThreadResult m)
runStepThread ids (Fork (ConcT ma) k) = do
  t &lt;- primFork False ma
  let (tid&#39;, ids&#39;) = nextThreadId ids
  pure (Just (k tid&#39;), ids&#39;, Forked t)
runStepThread ids (ForkOS (ConcT ma) k) = do
  t &lt;- primFork True ma
  let (tid&#39;, ids&#39;) = nextThreadId ids
  pure (Just (k tid&#39;), ids&#39;, Forked t)
runStepThread ids (NewEmptyMVar k) = do
  v &lt;- newEmptyMVar
  putMVar v Nothing
  let (mvid, ids&#39;) = nextMVarId ids
  let mvar = CTMVar mvid v
  pure (Just (k mvar), ids&#39;, BusinessAsUsual)
runStepThread ids k0@(PutMVar (CTMVar mvid v) a k) = do
  old &lt;- takeMVar v
  case old of
    Just _  -&gt; putMVar v old      &gt;&gt; pure (Just k0, ids, Blocked mvid)
    Nothing -&gt; putMVar v (Just a) &gt;&gt; pure (Just k, ids,  Updated mvid)
runStepThread ids k0@(TakeMVar (CTMVar mvid v) k) = do
  old &lt;- takeMVar v
  case old of
    Nothing -&gt; putMVar v old     &gt;&gt; pure (Just k0,    ids, Blocked mvid)
    Just a  -&gt; putMVar v Nothing &gt;&gt; pure (Just (k a), ids, Updated mvid)
runStepThread ids (Stop ma) = do
  ma
  pure (Nothing, ids, Killed)

primFork :: MonadConc m =&gt; Bool -&gt; K.Cont (Action m) () -&gt; m (Thread m)
primFork isOS ma = forkThread isOS (K.runCont ma (\_ -&gt; Stop (pure ())))</code></pre>
<p>This looks pretty horrible, but each case is fairly small, so just look at those.</p>
<p>Now we can run it (with a random scheduler for fun) and see that it works:</p>
<pre class="haskell literate"><code>test :: MonadConc m =&gt; m Int
test = do
  a &lt;- newEmptyMVar
  b &lt;- newMVar 2
  c &lt;- newMVar 3
  forkOS (putMVar a b)
  forkOS (putMVar a c)
  forkOS (takeMVar b &gt;&gt; putMVar b 14)
  forkOS (takeMVar c &gt;&gt; putMVar c 15)
  takeMVar =&lt;&lt; takeMVar a

randomSched :: Scheduler R.StdGen
randomSched (t:|ts) g =
  let (i, g&#39;) = R.randomR (0, length ts) g
  in ((t:ts) !! i, g&#39;)

main :: IO ()
main = do
  g &lt;- R.newStdGen
  print . fst =&lt;&lt; minifu randomSched g test</code></pre>
<p>Giving:</p>
<pre><code>λ&gt; main
Just 14
λ&gt; main
Just 2
λ&gt; main
Just 14
λ&gt; main
Just 2
λ&gt; main
Just 14
λ&gt; main
Just 14
λ&gt; main
Just 15
λ&gt; main
Just 15</code></pre>
<p>That wasn’t so bad!</p>
<h2 id="next-steps-to-deja-fu">Next Steps to Deja Fu</h2>
<p>Mini Fu is much smaller than Deja Fu, but it demonstrates the key concepts. To get a multithreaded runtime into dejafu, I think the main change to this stuff is to figure out how thread communication is going to work: in dejafu proper, actions can change the continuation of an arbitrary thread (eg, throwing an exception to a thread will call its exception handler).</p>
<p>The overhead of this method compared to the single-threaded approach must be measured. It would be great to support bound threads, but not at the cost of everything else becoming much worse! If the overhead is bad, perhaps a hybrid approach could be used: unbound threads in the program-under-test are executed as they are currently, whereas bound threads get the fancy multithreaded implementation. It would complicate things, but possibly eliminate the overhead in the common case.</p>
<p>Finally, when the main thread terminates, any still-running ones should terminate as well, so the <code>Thread</code> record will need to contain the <code>ThreadId m</code> of the underlying monad, so <code>killThread</code> can be used.</p>

      ]]>
    </summary>
  </entry>
  
  <entry>
    <title>Improving Performance by Discarding Traces</title>
    <link href="https://memo.barrucadu.co.uk/throwing-away-traces.html" />
    <id>https://memo.barrucadu.co.uk/throwing-away-traces.html</id>
    <published>2017-08-16T00:00:00Z</published>
    <updated>2017-08-16T00:00:00Z</updated>
    <summary type="html">
      <![CDATA[
<p><strong>tl;dr</strong> if you don’t want all the execution traces, you might now be able to run your dejafu tests with several thousand times less memory.</p>
<hr />
<p>dejafu leans more towards correctness than performance, by default. Your test cases will be executed using the <code>Test.DejaFu.SCT.sctBounded</code> function, which is complete but can be slow; every result you get will have an associated trace, which can be useful for debugging, but takes up memory.</p>
<p>dejafu-0.7.1.0 gives you an extra knob to tweak, and 0.7.1.1 makes it even better.</p>
<h2 id="discarding-results-and-traces-dejafu-0.7.1.0">Discarding results and traces (dejafu-0.7.1.0)</h2>
<figure>
<img src="throwing-away-traces/randomly-before.png" alt="Random testing before (with traces)" />
<figcaption aria-hidden="true">Random testing before (with traces)</figcaption>
</figure>
<figure>
<img src="throwing-away-traces/randomly-after.png" alt="Random testing after (without traces)" />
<figcaption aria-hidden="true">Random testing after (without traces)</figcaption>
</figure>
<p><strong>Full-size images:</strong> <a href="throwing-away-traces/randomly-before-full.pdf">before</a>, <a href="throwing-away-traces/randomly-after-full.pdf">after</a>.</p>
<p>Test cases with long traces have been a particularly bad case, as all the traces stuck around in memory until you did something with them at the end (like print the bad ones). This is such a case:</p>
<pre class="haskell"><code>contendedMVar :: MonadConc m =&gt; m ()
contendedMVar = do
  threadId &lt;- myThreadId
  mvar     &lt;- newEmptyMVar

  let maxval = 150
  let go = takeMVar mvar &gt;&gt;= \x -&gt; if x == maxval then killThread threadId else go

  for_ [1..20] . const $ fork go
  fork $ for_ [1..maxval] (putMVar mvar)

  takeMVar =&lt;&lt; newEmptyMVar</code></pre>
<p>I ran that 100 times with random scheduling, and the traces varied from about 2500 to 3000 elements long. That’s a lot of stuff to keep around in memory!</p>
<p>Sometimes you don’t want <em>all</em> the results or traces of your test case, you only want some of them. Now you can tell dejafu to throw things away as it’s running, allowing garbage collection to kick in sooner, and reduce the resident memory usage.</p>
<p>There’s a new type and some new functions:</p>
<pre class="haskell"><code>module Test.DejaFu.SCT where

-- ...

-- | An @Either Failure a -&gt; Maybe Discard@ value can be used to
-- selectively discard results.
--
-- @since 0.7.1.0
data Discard
  = DiscardTrace
  -- ^ Discard the trace but keep the result.  The result will appear
  -- to have an empty trace.
  | DiscardResultAndTrace
  -- ^ Discard the result and the trace.  It will simply not be
  -- reported as a possible behaviour of the program.
  deriving (Eq, Show, Read, Ord, Enum, Bounded)

-- | A variant of &#39;runSCT&#39; which can selectively discard results.
--
-- @since 0.7.1.0
runSCTDiscard :: MonadRef r n
  =&gt; (Either Failure a -&gt; Maybe Discard)
  -- ^ Selectively discard results.
  -&gt; Way
  -- ^ How to run the concurrent program.
  -&gt; MemType
  -- ^ The memory model to use for non-synchronised @CRef@ operations.
  -&gt; ConcT r n a
  -- ^ The computation to run many times.
  -&gt; n [(Either Failure a, Trace)]

-- and: runSCTDiscard&#39;, resultsSetDiscard, resultsSetDiscard&#39;, sctBoundDiscard,
--      sctUniformRandomDiscard, sctWeightedRandomDiscard
-- and: dejafuDiscard, dejafuDiscardIO         (Test.DejaFu)
-- and: testDejafuDiscard, testDejafuDiscardIO (Test.{HUnit,Tasty}.DejaFu)</code></pre>
<p>Every iteration of the SCT loop, an <code>Either Failure a</code> value is produced. The <code>*Discard</code> function variants will throw it (or its trace) away if you so tell it.</p>
<p>For example, you can now check that a test case doesn’t deadlock in a far more memory-efficient way like so:</p>
<pre class="haskell"><code>dejafuDiscard
  -- &quot;efa&quot; == &quot;either failure a&quot;, discard everything but deadlocks
  (\efa -&gt; if efa == Left Deadlock then Nothing else Just DiscardResultAndTrace)
  -- try 1000 executions with random scheduling
  (randomly (mkStdGen 42) 1000)
  -- use the default memory model
  defaultMemType
  -- your test case
  testCase
  -- the predicate to check (which is a bit redundant in this case)
  (&quot;Never Deadlocks&quot;, deadlocksNever)</code></pre>
<h2 id="a-much-improved-dpor-implementation-dejafu-0.7.1.1">A much improved DPOR implementation (dejafu-0.7.1.1)</h2>
<figure>
<img src="throwing-away-traces/systematically-before.png" alt="Systematic testing before (with traces)" />
<figcaption aria-hidden="true">Systematic testing before (with traces)</figcaption>
</figure>
<figure>
<img src="throwing-away-traces/systematically-after.png" alt="Systematic testing after (without traces)" />
<figcaption aria-hidden="true">Systematic testing after (without traces)</figcaption>
</figure>
<p><strong>Full-size images:</strong> <a href="throwing-away-traces/systematically-before-full.pdf">before</a>, <a href="throwing-away-traces/systematically-after-full.pdf">after</a>.</p>
<p>Unfortunately, 0.7.1.0 was only a win for random testing, as systematic testing explicitly constructed the tree of executions in memory. This has been a long-standing issue with dejafu, but I’d never gotten around to solving it before, because it wasn’t really any worse than what was happening elsewhere in the codebase. But now it was the worst!</p>
<p>The solution, in principle, was simple: you can avoid constructing the complete tree by instead exploring schedules in a depth-first fashion, which means you only need a stack and some bookkeeping information.</p>
<p>The implementation was fairly simple too! I like simple things.</p>
<p>So now we can check every possible execution of our test case for deadlocks, still in a memory-efficient fashion:</p>
<pre class="haskell"><code>dejafuDiscard
  (\efa -&gt; if efa == Left Deadlock then Nothing else Just DiscardResultAndTrace)
  -- the default way is systematic testing
  defaultWay
  defaultMemType
  testCase
  (&quot;Never Deadlocks&quot;, deadlocksNever)</code></pre>
<p>It’s not as memory-efficient as random scheduling, as it needs to keep around <em>some</em> information about prior executions, but the amount it is keeping around is greatly reduced from before.</p>
<hr />
<p>What’s next? I don’t really know. There are still a lot of memory inefficiencies in dejafu, but they all pale in comparison to these two, so they can probably sit for a while longer. I’d like to build a suite of benchmarks, because I don’t really have any other than the test suite (which makes a poor benchmark). If you have any test cases which dejafu just can’t handle, let me know!</p>
<p>I think it’s fair to say that the frontiers of what dejafu is capable of have been pushed back a <em>long</em> way by these changes.</p>

      ]]>
    </summary>
  </entry>
  
  <entry>
    <title>Property-testing Side Effects</title>
    <link href="https://memo.barrucadu.co.uk/property-testing-side-effects.html" />
    <id>https://memo.barrucadu.co.uk/property-testing-side-effects.html</id>
    <published>2017-06-09T00:00:00Z</published>
    <updated>2017-06-09T00:00:00Z</updated>
    <summary type="html">
      <![CDATA[
<p><a href="https://hackage.haskell.org/package/dejafu-0.7.0.0">dejafu-0.7.0.0</a> brings with it <a href="http://hackage.haskell.org/package/dejafu-0.7.0.0/docs/Test-DejaFu-Refinement.html">a new module</a> for property-testing the side-effects of stateful expressions. It’s just a wrapper around the unit-testing stuff dejafu always did, but it’s more convenient than handling things like supplying random arguments and comparing results yourself.</p>
<p>We can check if two expressions have equivalent behaviours, or if one has <em>fewer</em> behaviours than the other. Such properties can serve both as documentation and as regression tests.</p>
<p>Let’s dive straight into an example:</p>
<blockquote>
<p>Is <code>readMVar</code> equivalent to a <code>takeMVar</code> followed by a <code>putMVar</code>?</p>
</blockquote>
<p>We might phrase this property like so:</p>
<pre class="haskell"><code>prop_read_equiv_take_put =
  sig readMVar `equivalentTo` sig (\v -&gt; takeMVar v &gt;&gt;= putMVar v)</code></pre>
<h2 id="set-up">Set-up</h2>
<p>The property-testing uses <em>signatures</em>, where a signature tells dejafu how to (1) create a <em>new</em> state; (2) make some <em>observation</em> of the state; (3) concurrently <em>interfere</em> with the state in some way; and (4) the expression to evaluate.</p>
<h3 id="state-type">State type</h3>
<p>Properties are monomorphic, so we can’t directly express a property about <em>any</em> <code>MVar</code>, we need to pick a concrete type for its contents. Let’s just pick <code>Int</code>:</p>
<pre class="haskell"><code>type State = MVar ConcIO Int</code></pre>
<p>Properties operate in the <code>ConcIO</code> monad. There is no option to use <code>ConcST</code> yet, as I couldn’t get a nice interface working which didn’t break type inference in GHCi.</p>
<h3 id="initialisation">Initialisation</h3>
<p>The state is constructed using a pure <em>seed value</em> the property-checker generates. We want to consider both <em>full</em> and <em>empty</em> <code>MVar</code>s, so we’ll ask it to supply a <code>Maybe Int</code>:</p>
<pre class="haskell"><code>type Seed = Maybe Int</code></pre>
<p>The initialisation function we will include in the signature then just calls <code>newMVar</code> or <code>newEmptyMVar</code> as appropriate:</p>
<pre class="haskell"><code>makeMVar :: Seed -&gt; ConcIO State
makeMVar (Just x) = newMVar x
makeMVar Nothing  = newEmptyMVar</code></pre>
<p>Seed values are generated using <a href="https://hackage.haskell.org/package/leancheck">LeanCheck</a>, an enumerative property-based testing library.</p>
<h3 id="observation">Observation</h3>
<p>We want to know if the <code>MVar</code> contains a value when we observe it, and we want to know what that value is; another <code>Maybe</code>:</p>
<pre class="haskell"><code>type Observation = Maybe Int</code></pre>
<p>It is important that the observation function does not block, so we use <code>tryReadMVar</code> here rather than <code>readMVar</code> or <code>takeMVar</code>:</p>
<pre class="haskell"><code>observeMVar :: State -&gt; Seed -&gt; ConcIO Observation
observeMVar v _ = tryReadMVar v</code></pre>
<p>It does not matter if making the observation has side-effects, so <code>tryTakeMVar</code> would have been equally valid.</p>
<h3 id="interference">Interference</h3>
<p>Our interference function will just mess with the value in the <code>MVar</code>:</p>
<pre class="haskell"><code>interfereMVar :: State -&gt; Seed -&gt; ConcIO ()
interfereMVar mvar mx = do
  tryTakeMVar mvar
  void . tryPutMVar mvar $ case mx of
    Just x  -&gt; (x+1) * 3000
    Nothing -&gt; 7000</code></pre>
<p>As LeanCheck is enumerative, large values like 3000 and 7000 will stand out if the tool reports a failure.</p>
<h3 id="signature">Signature</h3>
<p>Now we package these operations up into a signature:</p>
<pre class="haskell"><code>sig :: (State -&gt; ConcIO a) -&gt; Sig State Observation Seed
sig e = Sig
  { initialise = makeMVar
  , observe    = observeMVar
  , interfere  = interfereMVar
  , expression = void . e
  }</code></pre>
<p>We could, of course, have defined all this inside <code>sig</code> without the top-level functions and type synonyms.</p>
<h2 id="properties">Properties</h2>
<p>Now we can test the property:</p>
<pre><code>&gt; check $ sig readMVar `equivalentTo` sig (\v -&gt; takeMVar v &gt;&gt;= putMVar v)
*** Failure: (seed Just 0)
    left:  [(Nothing,Just 3000)]
    right: [(Nothing,Just 0),(Nothing,Just 3000),(Just Deadlock,Just 3000)]</code></pre>
<p>We get a failure! This is because the left term is atomic, whereas the right is not: another thread writing to the <code>MVar</code> has the opportunity to swoop in and insert a new value after the <code>takeMVar</code> but before the <code>putMVar</code>. The right has strictly more behaviours than the left.</p>
<p>We can capture this, by using a different comparison:</p>
<pre><code>&gt; check $ sig readMVar `strictlyRefines` sig (\v -&gt; takeMVar v &gt;&gt;= putMVar v)
+++ OK</code></pre>
<p>To “strictly refine” something is to have a proper subset of the behaviour. There is also a “refines” comparison, which does not require the subset to be proper.</p>
<h3 id="wait-a-minute">Wait a minute…</h3>
<ul>
<li><p>Doesn’t <code>readMVar v</code> return a different thing to <code>takeMVar v &gt;&gt;= putMVar v</code>?</p>
<p><em>Yes!</em></p>
<p>If they return at all, the former returns the value in the <code>MVar</code>, whereas the latter returns unit. Properties do not care about the return value of an expression, only the effects.</p>
<p>You can see this by looking at the definition of <code>sig</code> again: it throws away the result of the expression using <code>void</code>.</p></li>
<li><p>Both of our properties are of the form <code>sig f `cmp` sig g</code>, can’t that redundancy be removed?</p>
<p><em>No!</em></p>
<p>You can use <em>different</em> signatures with <em>different</em> state types! As long as the seed and observation types are the same, <code>check</code> can compare them.</p>
<p>You can use this to compare different implementations of a similar concurrent data structure.</p></li>
</ul>
<h3 id="properties-with-arguments">Properties with arguments</h3>
<p>Properties can also have arguments, using LeanCheck to generate their values. This doesn’t work in any mysterious way, here’s a property about the <a href="https://hackage.haskell.org/package/concurrency-1.1.2.1/docs/Control-Concurrent-Classy-QSemN.html"><code>QSemN</code></a> functions:</p>
<pre><code>&gt; check $ \x y -&gt; sig&#39; (\v -&gt; signalQSemN v (x + y)) `equivalentTo` sig&#39; (\v -&gt; signalQSemN v x &gt;&gt; signalQSemN v y)
*** Failure: -1 1 (seed 0)
    left:  [(Nothing,0)]
    right: [(Nothing,0),(Just Deadlock,0)]</code></pre>
<p>You can even use your own types, as long as they have a <code>Listable</code> (the typeclass LeanCheck uses) instance:</p>
<pre><code>&gt; :{
newtype Nat n = Nat n deriving Show
instance (Num n, Ord n, Listable n) =&gt; Listable (Nat n) where
  list = [Nat n | n &lt;- list, n &gt;= 0]
:}

&gt; check $ \(Nat x) (Nat y) -&gt; sig&#39; (\v -&gt; signalQSemN v (x + y)) `equivalentTo` sig&#39; (\v -&gt; signalQSemN v x &gt;&gt; signalQSemN v y)
+++ OK!</code></pre>
<p>Currently it’s a bit slow as I need to fiddle with the implementation and work out what a good number of tests to run is. <code>check</code> uses 10 seed values with 100 variable assignments each (1000 tests total), you can use <code>checkFor</code> to reduce that.</p>
<h2 id="fin">Fin</h2>
<p>So there you have it, property-testing for side-effects of stateful operations.</p>
<p>This has come out of my work on <a href="https://github.com/barrucadu/coco">CoCo</a>, a tool for automatically <em>discovering</em> these properties (<a href="https://www.barrucadu.co.uk/publications/coco-tfp17-prelim.pdf">paper here</a>). In the CoCo repository are a few more examples. CoCo is still a work-in-progress, but one of the goals is to be able to generate dejafu-compatible output, so that CoCo can discover properties which dejafu can immediately begin using for regression testing.</p>

      ]]>
    </summary>
  </entry>
  
</feed>