MCPcopy Create free account
hub / github.com/cameron314/concurrentqueue / try_get

Method try_get

concurrentqueue.h:1495–1532  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1493 }
1494
1495 inline N* try_get()
1496 {
1497#ifdef MCDBGQ_NOLOCKFREE_FREELIST
1498 debug::DebugLock lock(mutex);
1499#endif
1500 auto head = freeListHead.load(std::memory_order_acquire);
1501 while (head != nullptr) {
1502 auto prevHead = head;
1503 auto refs = head->freeListRefs.load(std::memory_order_relaxed);
1504 if ((refs & REFS_MASK) == 0 || !head->freeListRefs.compare_exchange_strong(refs, refs + 1, std::memory_order_acquire)) {
1505 head = freeListHead.load(std::memory_order_acquire);
1506 continue;
1507 }
1508
1509 // Good, reference count has been incremented (it wasn't at zero), which means we can read the
1510 // next and not worry about it changing between now and the time we do the CAS
1511 auto next = head->freeListNext.load(std::memory_order_relaxed);
1512 if (freeListHead.compare_exchange_strong(head, next, std::memory_order_acquire, std::memory_order_relaxed)) {
1513 // Yay, got the node. This means it was on the list, which means shouldBeOnFreeList must be false no
1514 // matter the refcount (because nobody else knows it's been taken off yet, it can't have been put back on).
1515 assert((head->freeListRefs.load(std::memory_order_relaxed) & SHOULD_BE_ON_FREELIST) == 0);
1516
1517 // Decrease refcount twice, once for our ref, and once for the list's ref
1518 head->freeListRefs.fetch_sub(2, std::memory_order_release);
1519 return head;
1520 }
1521
1522 // OK, the head must have changed on us, but we still need to decrease the refcount we increased.
1523 // Note that we don't need to release any memory effects, but we do need to ensure that the reference
1524 // count decrement happens-after the CAS on the head.
1525 refs = prevHead->freeListRefs.fetch_sub(1, std::memory_order_acq_rel);
1526 if (refs == SHOULD_BE_ON_FREELIST + 1) {
1527 add_knowing_refcount_is_zero(prevHead);
1528 }
1529 }
1530
1531 return nullptr;
1532 }
1533
1534 // Useful for traversing the list when there's no contention (e.g. to destroy remaining nodes)
1535 N* head_unsafe() const { return freeListHead.load(std::memory_order_relaxed); }

Callers 1

Calls 4

assertClass · 0.85
loadMethod · 0.45
fetch_subMethod · 0.45

Tested by

no test coverage detected