Skip to content

handle UnboundedBlockingMpscQueue spurious wake-ups

Maxim Onciul requested to merge ubmpscq_handle_spurious_wakeup into master

A spurious wake-up can be produced by the new UnblockOnMainActorTest which triggers the assert(!mpscQueue.empty()) in UnboundedBlockingMpscQueue::get.

Those spurious wake-ups are possible because the push and wake-up pair in UnboundedBlockingMpscQueue::put are not atomic. The following sequence diagram demonstrates a spurious wake-up:

   T1          T2            Q
   .           .            { }
  put(e)       .            { }
 push 54-57    .            {e}
   .         get()          {e}
   .        consume e       { }
   .           .            { }
   .         get()          { }
   .         block          { }
 unblock       .            { }
   .           .            { }
   .         wakeup         { }
   .           .            { }
               X
       assert(!queue.Empty())

To deal with spurious wake-ups we recheck the wake-up condition (a non empty queue) and block again if we find it empty. We assume spurious wake-ups are rare because it was difficult to reproduce them even with a dedicated Test (the new UnblockOnMainActorTest) therefore we declare the empty queue branch as unlikely.

Fixes #4 (closed).

Edited by Maxim Onciul

Merge request reports

Loading