diff options
author | gulin <gulin@yandex-team.ru> | 2022-02-10 16:47:32 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:47:32 +0300 |
commit | 7199613d295246a07c2f7b331fbb3128936039dc (patch) | |
tree | c0748b5dcbade83af788c0abfa89c0383d6b779c /util/thread/lfstack.h | |
parent | c807aae441c17fc7f577c35757a4b6e0bd909802 (diff) | |
download | ydb-7199613d295246a07c2f7b331fbb3128936039dc.tar.gz |
Restoring authorship annotation for <gulin@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'util/thread/lfstack.h')
-rw-r--r-- | util/thread/lfstack.h | 82 |
1 files changed, 41 insertions, 41 deletions
diff --git a/util/thread/lfstack.h b/util/thread/lfstack.h index 98135e1ee9..ca3d95f3c3 100644 --- a/util/thread/lfstack.h +++ b/util/thread/lfstack.h @@ -121,66 +121,66 @@ public: AtomicAdd(DequeueCount, -1); return false; } - // add all elements to *res + // add all elements to *res // elements are returned in order of dequeue (top to bottom; see example in unittest) template <typename TCollection> void DequeueAll(TCollection* res) { - AtomicAdd(DequeueCount, 1); + AtomicAdd(DequeueCount, 1); for (TNode* current = AtomicGet(Head); current; current = AtomicGet(Head)) { if (AtomicCas(&Head, (TNode*)nullptr, current)) { for (TNode* x = current; x;) { res->push_back(std::move(x->Value)); - x = x->Next; - } - // EraseList(current); // ABA problem - // even more complex node deletion - TryToFreeMemory(); - if (AtomicAdd(DequeueCount, -1) == 0) { - // no other Dequeue()s, can safely reclaim memory - EraseList(current); - } else { - // Dequeue()s in progress, add nodes list to free list + x = x->Next; + } + // EraseList(current); // ABA problem + // even more complex node deletion + TryToFreeMemory(); + if (AtomicAdd(DequeueCount, -1) == 0) { + // no other Dequeue()s, can safely reclaim memory + EraseList(current); + } else { + // Dequeue()s in progress, add nodes list to free list TNode* currentLast = current; - while (currentLast->Next) { + while (currentLast->Next) { currentLast = currentLast->Next; - } - for (;;) { + } + for (;;) { AtomicSet(currentLast->Next, AtomicGet(FreePtr)); - if (AtomicCas(&FreePtr, current, currentLast->Next)) - break; - } - } - return; - } - } - TryToFreeMemory(); - AtomicAdd(DequeueCount, -1); - } + if (AtomicCas(&FreePtr, current, currentLast->Next)) + break; + } + } + return; + } + } + TryToFreeMemory(); + AtomicAdd(DequeueCount, -1); + } bool DequeueSingleConsumer(T* res) { for (TNode* current = AtomicGet(Head); current; current = AtomicGet(Head)) { - if (AtomicCas(&Head, current->Next, current)) { + if (AtomicCas(&Head, current->Next, current)) { *res = std::move(current->Value); - delete current; // with single consumer thread ABA does not happen - return true; - } - } - return false; - } - // add all elements to *res - // elements are returned in order of dequeue (top to bottom; see example in unittest) + delete current; // with single consumer thread ABA does not happen + return true; + } + } + return false; + } + // add all elements to *res + // elements are returned in order of dequeue (top to bottom; see example in unittest) template <typename TCollection> void DequeueAllSingleConsumer(TCollection* res) { for (TNode* current = AtomicGet(Head); current; current = AtomicGet(Head)) { if (AtomicCas(&Head, (TNode*)nullptr, current)) { for (TNode* x = current; x;) { res->push_back(std::move(x->Value)); - x = x->Next; - } - EraseList(current); // with single consumer thread ABA does not happen - return; - } - } - } + x = x->Next; + } + EraseList(current); // with single consumer thread ABA does not happen + return; + } + } + } bool IsEmpty() { AtomicAdd(DequeueCount, 0); // mem barrier return AtomicGet(Head) == nullptr; // without lock, so result is approximate |