aboutsummaryrefslogtreecommitdiffstats
path: root/util/thread/lfstack.h
diff options
context:
space:
mode:
authorAnton Samokhvalov <pg83@yandex.ru>2022-02-10 16:45:15 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:15 +0300
commit72cb13b4aff9bc9cf22e49251bc8fd143f82538f (patch)
treeda2c34829458c7d4e74bdfbdf85dff449e9e7fb8 /util/thread/lfstack.h
parent778e51ba091dc39e7b7fcab2b9cf4dbedfb6f2b5 (diff)
downloadydb-72cb13b4aff9bc9cf22e49251bc8fd143f82538f.tar.gz
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 1 of 2.
Diffstat (limited to 'util/thread/lfstack.h')
-rw-r--r--util/thread/lfstack.h66
1 files changed, 33 insertions, 33 deletions
diff --git a/util/thread/lfstack.h b/util/thread/lfstack.h
index ca3d95f3c3..aa64ce1dbe 100644
--- a/util/thread/lfstack.h
+++ b/util/thread/lfstack.h
@@ -5,31 +5,31 @@
//////////////////////////////
// lock free lifo stack
-template <class T>
-class TLockFreeStack: TNonCopyable {
- struct TNode {
+template <class T>
+class TLockFreeStack: TNonCopyable {
+ struct TNode {
T Value;
- TNode* Next;
+ TNode* Next;
TNode() = default;
- template <class U>
+ template <class U>
explicit TNode(U&& val)
: Value(std::forward<U>(val))
, Next(nullptr)
- {
- }
+ {
+ }
};
TNode* Head;
TNode* FreePtr;
TAtomic DequeueCount;
- void TryToFreeMemory() {
+ void TryToFreeMemory() {
TNode* current = AtomicGet(FreePtr);
if (!current)
return;
- if (AtomicAdd(DequeueCount, 0) == 1) {
+ if (AtomicAdd(DequeueCount, 0) == 1) {
// node current is in free list, we are the last thread so try to cleanup
if (AtomicCas(&FreePtr, (TNode*)nullptr, current))
EraseList(current);
@@ -37,7 +37,7 @@ class TLockFreeStack: TNonCopyable {
}
void EraseList(TNode* volatile p) {
while (p) {
- TNode* next = p->Next;
+ TNode* next = p->Next;
delete p;
p = next;
}
@@ -54,20 +54,20 @@ class TLockFreeStack: TNonCopyable {
TNode* volatile node = new TNode(std::forward<U>(u));
EnqueueImpl(node, node);
}
-
+
public:
- TLockFreeStack()
+ TLockFreeStack()
: Head(nullptr)
, FreePtr(nullptr)
- , DequeueCount(0)
- {
- }
- ~TLockFreeStack() {
+ , DequeueCount(0)
+ {
+ }
+ ~TLockFreeStack() {
EraseList(Head);
EraseList(FreePtr);
}
- void Enqueue(const T& t) {
+ void Enqueue(const T& t) {
EnqueueImpl(t);
}
@@ -76,11 +76,11 @@ public:
}
template <typename TCollection>
- void EnqueueAll(const TCollection& data) {
+ void EnqueueAll(const TCollection& data) {
EnqueueAll(data.begin(), data.end());
}
template <typename TIter>
- void EnqueueAll(TIter dataBegin, TIter dataEnd) {
+ void EnqueueAll(TIter dataBegin, TIter dataEnd) {
if (dataBegin == dataEnd) {
return;
}
@@ -95,22 +95,22 @@ public:
}
EnqueueImpl(node, tail);
}
- bool Dequeue(T* res) {
- AtomicAdd(DequeueCount, 1);
+ bool Dequeue(T* res) {
+ AtomicAdd(DequeueCount, 1);
for (TNode* current = AtomicGet(Head); current; current = AtomicGet(Head)) {
if (AtomicCas(&Head, AtomicGet(current->Next), current)) {
*res = std::move(current->Value);
// delete current; // ABA problem
// even more complex node deletion
TryToFreeMemory();
- if (AtomicAdd(DequeueCount, -1) == 0) {
+ if (AtomicAdd(DequeueCount, -1) == 0) {
// no other Dequeue()s, can safely reclaim memory
delete current;
} else {
// Dequeue()s in progress, put node to free list
- for (;;) {
+ for (;;) {
AtomicSet(current->Next, AtomicGet(FreePtr));
- if (AtomicCas(&FreePtr, current, current->Next))
+ if (AtomicCas(&FreePtr, current, current->Next))
break;
}
}
@@ -118,17 +118,17 @@ public:
}
}
TryToFreeMemory();
- AtomicAdd(DequeueCount, -1);
+ AtomicAdd(DequeueCount, -1);
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 DequeueAll(TCollection* res) {
+ void DequeueAll(TCollection* res) {
AtomicAdd(DequeueCount, 1);
for (TNode* current = AtomicGet(Head); current; current = AtomicGet(Head)) {
if (AtomicCas(&Head, (TNode*)nullptr, current)) {
- for (TNode* x = current; x;) {
+ for (TNode* x = current; x;) {
res->push_back(std::move(x->Value));
x = x->Next;
}
@@ -140,9 +140,9 @@ public:
EraseList(current);
} else {
// Dequeue()s in progress, add nodes list to free list
- TNode* currentLast = current;
+ TNode* currentLast = current;
while (currentLast->Next) {
- currentLast = currentLast->Next;
+ currentLast = currentLast->Next;
}
for (;;) {
AtomicSet(currentLast->Next, AtomicGet(FreePtr));
@@ -156,7 +156,7 @@ public:
TryToFreeMemory();
AtomicAdd(DequeueCount, -1);
}
- bool DequeueSingleConsumer(T* res) {
+ bool DequeueSingleConsumer(T* res) {
for (TNode* current = AtomicGet(Head); current; current = AtomicGet(Head)) {
if (AtomicCas(&Head, current->Next, current)) {
*res = std::move(current->Value);
@@ -169,10 +169,10 @@ public:
// 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) {
+ void DequeueAllSingleConsumer(TCollection* res) {
for (TNode* current = AtomicGet(Head); current; current = AtomicGet(Head)) {
if (AtomicCas(&Head, (TNode*)nullptr, current)) {
- for (TNode* x = current; x;) {
+ for (TNode* x = current; x;) {
res->push_back(std::move(x->Value));
x = x->Next;
}
@@ -181,7 +181,7 @@ public:
}
}
}
- bool IsEmpty() {
+ bool IsEmpty() {
AtomicAdd(DequeueCount, 0); // mem barrier
return AtomicGet(Head) == nullptr; // without lock, so result is approximate
}