title: Writing a (spinning) thread barrier using c++11 atomics
body: <p>I'm trying to familiarize myself with c++11 atomics, so I tried writing a barrier class for threads (before someone complains about not using existing classes: this is more for learning/self improvement than due to any real need). my class looks basically as followed:</p>
  
  <pre><code>class barrier
  {
  private:
      std::atomic&lt;int&gt; counter[2];
      std::atomic&lt;int&gt; lock[2];
      std::atomic&lt;int&gt; cur_idx;
      int thread_count;
  public:
      //constructors...
      bool wait();
  };
  </code></pre>
  
  <p>All members are initialized to zero, except thread_count, which holds the appropriate count.
  I have implemented the wait function as</p>
  
  <pre><code>int idx  = cur_idx.load();
  if(lock[idx].load() == 0)
  {
      lock[idx].store(1);
  }
  int val = counter[idx].fetch_add(1);
  if(val &gt;= thread_count - 1)
  {
      counter[idx].store(0);
      cur_idx.fetch_xor(1);
      lock[idx].store(0);
      return true;
  }
  while(lock[idx].load() == 1);
  return false;
  </code></pre>
  
  <p>However when trying to use it with two threads (<code>thread_count</code> is 2) whe first thread gets in the wait loop just fine, but the second thread doesn't unlock the barrier (it seems it doesn't even get to <code>int val = counter[idx].fetch_add(1);</code>, but I'm not too sure about that. However when I'm using gcc atomic-intrinsics by using <code>volatile int</code> instead of <code>std::atomic&lt;int&gt;</code> and writing <code>wait</code> as followed:</p>
  
  <pre><code>int idx = cur_idx;
  if(lock[idx] == 0)
  {
      __sync_val_compare_and_swap(&amp;lock[idx], 0, 1);
  }
  int val = __sync_fetch_and_add(&amp;counter[idx], 1);
  if(val &gt;= thread_count - 1)
  {
      __sync_synchronize();
      counter[idx] = 0;
      cur_idx ^= 1;
      __sync_synchronize();
      lock[idx] = 0;
      __sync_synchronize();
      return true;
  }
  while(lock[idx] == 1);
  return false;
  </code></pre>
  
  <p>it works just fine. From my understanding there shouldn't be any fundamental differences between the two versions (more to the point if anything the second should be less likely to work). So which of the following scenarios applies?</p>
  
  <ol>
  <li>I got lucky with the second implementation and my algorithm is crap</li>
  <li>I didn't fully understand <code>std::atomic</code> and there is a problem with the first variant (but not the second)</li>
  <li>It should work, but the experimental implementation for c++11 libraries isn't as mature as I have hoped</li>
  </ol>
  
  <p>For the record I'm using 32bit mingw with gcc 4.6.1</p>
  
  <p>The calling code looks like this:</p>
  
  <pre><code>spin_barrier b(2);
  std::thread t([&amp;b]()-&gt;void
  {
      std::this_thread::sleep_for(std::chrono::duration&lt;double&gt;(0.1));
      b.wait();
  });
  b.wait();
  t.join();
  </code></pre>
  
  <p>Since mingw doesn't whave <code>&lt;thread&gt;</code> headers jet I use a self written version for that which basically wraps the appropriate  pthread functions (before someone asks: yes it works without the barrier, so it shouldn't be a problem with the wrapping)
  Any insights would be appreciated.</p>
  
  <p>edit: Explanation for the algorithm to make it clearer:</p>
  
  <ul>
  <li><code>thread_count</code> is the number of threads which shall wait for the barrier (so if <code>thread_count</code> threads are in the barrier all can leave the barrier).</li>
  <li><code>lock</code> is set to one when the first (or any) thread enters the barrier.</li>
  <li><code>counter</code> counts how many threads are inside the barrier and is atomically incremented once for each thread</li>
  <li><code>if counter&gt;=thread_count</code> all threads are inside the barrier so counter and lock are reset to zero</li>
  <li>otherwise the thread waits for the <code>lock</code> to become zero</li>
  <li>in the next use of the barrier different variables (<code>counter</code>, <code>lock</code>) are used ensure there are no problems if threads are still waiting on the first use of the barrier (e.g. they had been preempted when the barrier is lifted)</li>
  </ul>
  
  <p>edit2:
  I have now tested it using gcc 4.5.1 under linux, where both versions seem to work just fine, which seems to point to a problem with mingw's <code>std::atomic</code>, but I'm still not completely convinced, since looking into the <code>&lt;atomic&gt;</code> header revaled that most functions simply call the appropriate gcc-atomic meaning there really shouldn't bea difference between the two versions</p>