| 1546 | // Returns true if the block is now empty (does not apply in explicit context). |
| 1547 | template<InnerQueueContext context> |
| 1548 | inline bool set_many_empty(index_t i, size_t count) { |
| 1549 | if (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) { |
| 1550 | // Set flags |
| 1551 | std::atomic_thread_fence(std::memory_order_release); |
| 1552 | i = BLOCK_SIZE - 1 - static_cast<size_t>(i & static_cast<index_t>(BLOCK_SIZE - 1)) - count + |
| 1553 | 1; |
| 1554 | for (size_t j = 0; j != count; ++j) { |
| 1555 | assert(!emptyFlags[i + j].load(std::memory_order_relaxed)); |
| 1556 | emptyFlags[i + j].store(true, std::memory_order_relaxed); |
| 1557 | } |
| 1558 | return false; |
| 1559 | } else { |
| 1560 | // Increment counter |
| 1561 | auto prevVal = elementsCompletelyDequeued.fetch_add(count, std::memory_order_release); |
| 1562 | assert(prevVal + count <= BLOCK_SIZE); |
| 1563 | return prevVal + count == BLOCK_SIZE; |
| 1564 | } |
| 1565 | } |
| 1566 | |
| 1567 | template<InnerQueueContext context> |
| 1568 | inline void set_all_empty() { |
nothing calls this directly
no outgoing calls
no test coverage detected