Pop an item from the queue. Returns true on popped and the item is written to `val'. May run in parallel with steal(). Never run in parallel with push() or another pop().
| 85 | // May run in parallel with steal(). |
| 86 | // Never run in parallel with push() or another pop(). |
| 87 | bool pop(T* val) { |
| 88 | const size_t b = _bottom.load(butil::memory_order_relaxed); |
| 89 | size_t t = _top.load(butil::memory_order_relaxed); |
| 90 | if (t >= b) { |
| 91 | // fast check since we call pop() in each sched. |
| 92 | // Stale _top which is smaller should not enter this branch. |
| 93 | return false; |
| 94 | } |
| 95 | const size_t newb = b - 1; |
| 96 | _bottom.store(newb, butil::memory_order_relaxed); |
| 97 | butil::atomic_thread_fence(butil::memory_order_seq_cst); |
| 98 | t = _top.load(butil::memory_order_relaxed); |
| 99 | if (t > newb) { |
| 100 | _bottom.store(b, butil::memory_order_relaxed); |
| 101 | return false; |
| 102 | } |
| 103 | *val = _buffer[newb & (_capacity - 1)]; |
| 104 | if (t != newb) { |
| 105 | return true; |
| 106 | } |
| 107 | // Single last element, compete with steal() |
| 108 | const bool popped = _top.compare_exchange_strong( |
| 109 | t, t + 1, butil::memory_order_seq_cst, butil::memory_order_relaxed); |
| 110 | _bottom.store(b, butil::memory_order_relaxed); |
| 111 | return popped; |
| 112 | } |
| 113 | |
| 114 | // Steal one item from the queue. |
| 115 | // Returns true on stolen. |
nothing calls this directly
no test coverage detected