| 1500 | |
| 1501 | template<InnerQueueContext context> |
| 1502 | inline bool is_empty() const { |
| 1503 | if (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) { |
| 1504 | // Check flags |
| 1505 | for (size_t i = 0; i < BLOCK_SIZE; ++i) { |
| 1506 | if (!emptyFlags[i].load(std::memory_order_relaxed)) { |
| 1507 | return false; |
| 1508 | } |
| 1509 | } |
| 1510 | |
| 1511 | // Aha, empty; make sure we have all other memory effects that happened before the empty flags were set |
| 1512 | std::atomic_thread_fence(std::memory_order_acquire); |
| 1513 | return true; |
| 1514 | } else { |
| 1515 | // Check counter |
| 1516 | if (elementsCompletelyDequeued.load(std::memory_order_relaxed) == BLOCK_SIZE) { |
| 1517 | std::atomic_thread_fence(std::memory_order_acquire); |
| 1518 | return true; |
| 1519 | } |
| 1520 | assert(elementsCompletelyDequeued.load(std::memory_order_relaxed) <= BLOCK_SIZE); |
| 1521 | return false; |
| 1522 | } |
| 1523 | } |
| 1524 | |
| 1525 | // Returns true if the block is now empty (does not apply in explicit context) |
| 1526 | template<InnerQueueContext context> |
nothing calls this directly
no outgoing calls
no test coverage detected