title: Is an efficient C++ conditional spinlock possible?
body: <p>I have a situation in multi-threaded C++ code where I need to make some very fast operations atomic (appear serialised) so I can use a spinlock such as:</p>
  
  <pre><code>lock mutex: while (lock.test_and_set(std::memory_order_acquire))
  unlock mutex: lock.clear(std::memory_order_release);
  </code></pre>
  
  <p>However I thought to be clever, and make the locking conditional on whether the data structure is currently shared by more than one thread or not:</p>
  
  <pre><code>lock mutex: if(lockneeded) while (lock.test_and_set(std::memory_order_acquire))
  unlock mutex: if(lockneeded)lock.clear(std::memory_order_release);
  </code></pre>
  
  <p>Initially, the data structure is owned by only one thread but access can be granted to another thread <em>by the owner</em> at which point it has to set the lock-needed variable (which has to be an atomic bool itself).</p>
  
  <p>Will this work? </p>
  
  <hr>
  
  <p>EDIT: some context. I have a system which schedules coroutines. A queue of suspended coroutines is run one at a time by a single thread until it suspends or completes, then the next one is run. This system was originally designed for a single thread, since coroutines by specification are sequential programming constructs. The context switching time is extremely fast because coroutines use heap allocated linked lists for stacks, not the machine stack. So a context switch is basically just a pointer swap.</p>
  
  <p>Then I decided to optionally allow more than one thread to process the list, so the coroutines become processes. Now the pointer swaps must be done atomically. The swaps are extremely fast, so a spinlock seems like the right way to guard the operations.</p>
  
  <p>I have a test case, where I run a set of jobs serially, then do it again with extra helper threads. I had a problem which i have now fixed that turned out to be unrelated to scheduling. Now, 4 threads run the process about 3.5 times faster than 1.</p>
  
  <p>The performance objective is simple: I want to wipe Go-lang off the face of the planet. My system is C/C++ ABI compliant (Go isn't), it uses the correct model for stream processing (Go doesn't), and its a hands down vastly superior language as well.</p>
  
  <p>I don't know how fast Go can context switch. But the current untuned version of my test case, in which we must not forget jobs count to 100K to create a delay (and ensure near zero contention on the lock), is processing 2 MILLION processes in 5 seconds, which is a context switching rate of about 400K switches per second. I expect if I replace the slow jobs with null jobs (do nothing coroutines), the rate will exceed 1 milllion switches per second. That's running 2 million processes. The real world speed will be lower, the experiment is trying to find the upper bound on performance.</p>