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.h28
1 files changed, 28 insertions, 0 deletions
diff --git a/include/salticidae/queue.h b/include/salticidae/queue.h
index 88b3fc3..9045e2b 100644
--- a/include/salticidae/queue.h
+++ b/include/salticidae/queue.h
@@ -90,6 +90,7 @@ class FreeList {
template<typename T>
class MPMCQueue {
+ protected:
struct Block: public FreeList::Node {
T elem;
std::atomic<Block *> next;
@@ -171,6 +172,33 @@ class MPMCQueue {
}
};
+template<typename T>
+struct MPSCQueue: public MPMCQueue<T> {
+ using MPMCQueue<T>::MPMCQueue;
+ bool try_dequeue(T &e) {
+ auto h = this->head.load(std::memory_order_acquire);
+ auto nh = h->next.load(std::memory_order_relaxed);
+ if (nh == nullptr)
+ return false;
+ e = std::move(nh->elem);
+ this->head.store(nh, std::memory_order_release);
+ this->blks.push(h);
+ return true;
+ }
+
+ template<typename U>
+ bool rewind(U &&e) {
+ FreeList::Node * _nblk;
+ if (!this->blks.pop(_nblk)) return false;
+ auto nblk = static_cast<typename MPMCQueue<T>::Block *>(_nblk);
+ auto h = this->head.load(std::memory_order_acquire);
+ nblk->next.store(h, std::memory_order_release);
+ new (&(h->elem)) T(std::forward<U>(e));
+ this->head.store(nblk, std::memory_order_release);
+ return true;
+ }
+};
+
}
#endif