aboutsummaryrefslogtreecommitdiff
path: root/include/salticidae/queue.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/salticidae/queue.h')
-rw-r--r--include/salticidae/queue.h20
1 files changed, 15 insertions, 5 deletions
diff --git a/include/salticidae/queue.h b/include/salticidae/queue.h
index 0417750..da11e8a 100644
--- a/include/salticidae/queue.h
+++ b/include/salticidae/queue.h
@@ -15,7 +15,8 @@ class FreeList {
struct Node {
std::atomic<Node *> next;
std::atomic<size_t> refcnt;
- Node(): next(nullptr), refcnt(1) {}
+ std::atomic<bool> freed;
+ Node(): next(nullptr), refcnt(1), freed(false) {}
};
private:
@@ -37,15 +38,16 @@ class FreeList {
// the replacement is ok even if ABA happens
if (top.compare_exchange_weak(t, u, std::memory_order_release))
{
+ // must have seen freed == true
u->refcnt.store(1, std::memory_order_relaxed);
break;
}
}
}
- bool push(Node *u) {
+ inline void push(Node *u) {
+ u->freed.store(true, std::memory_order_relaxed);
release_ref(u);
- return true;
}
bool pop(Node *&r) {
@@ -110,6 +112,11 @@ class MPMCQueue {
if (!tcnt) continue;
if (!t->refcnt.compare_exchange_weak(tcnt, tcnt + 1, std::memory_order_relaxed))
continue;
+ if (t->freed.load(std::memory_order_relaxed))
+ {
+ blks.release_ref(t);
+ continue;
+ }
auto tt = t->tail.load(std::memory_order_relaxed);
if (tt >= MPMCQ_SIZE)
{
@@ -130,9 +137,12 @@ class MPMCQueue {
nblk->next.store(nullptr, std::memory_order_relaxed);
Block *tnext = nullptr;
if (!t->next.compare_exchange_weak(tnext, nblk, std::memory_order_acq_rel))
- blks.push(_nblk);
+ blks.push(nblk);
else
- tail.store(nblk, std::memory_order_relaxed);
+ {
+ tail.store(nblk, std::memory_order_release);
+ nblk->freed.store(false, std::memory_order_release);
+ }
}
blks.release_ref(t);
continue;