From 4185927983fa5cd4b39887d62628af0056ce2d0b Mon Sep 17 00:00:00 2001
From: Vegard Storheil Eriksen <zyp@jvnv.net>
Date: Sat, 10 Sep 2022 17:11:47 +0200
Subject: async: Add queue.

---
 async/queue.h | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 async/queue.h

(limited to 'async')

diff --git a/async/queue.h b/async/queue.h
new file mode 100644
index 0000000..965e9b9
--- /dev/null
+++ b/async/queue.h
@@ -0,0 +1,59 @@
+#pragma once
+
+template <typename T, std::size_t N>
+struct queue {
+    std::array<T, N> data;
+    volatile std::size_t put_idx;
+    volatile std::size_t get_idx;
+
+    async_flag put_flag;
+    async_flag get_flag;
+
+    constexpr std::size_t _inc(std::size_t n) {
+        return n + 1 < N ? n + 1 : 0;
+    }
+
+    bool empty() {
+        return put_idx == get_idx;
+    }
+
+    bool full() {
+        return _inc(put_idx) == get_idx;
+    }
+
+    bool put(T v) {
+        if(full()) {
+            return false;
+        }
+
+        data[put_idx] = v;
+        put_idx = _inc(put_idx);
+        put_flag.set();
+        return true;
+    }
+
+    bool get(T& v) {
+        if(empty()) {
+            return false;
+        }
+
+        v = data[get_idx];
+        get_idx = _inc(get_idx);
+        get_flag.set();
+        return true;
+    }
+
+    async<> async_put(T v) {
+        while(!put(v)) {
+            co_await get_flag;
+        }
+    }
+
+    async<T> async_get() {
+        T v;
+        while(!get(v)) {
+            co_await put_flag;
+        }
+        co_return v;
+    }
+};
-- 
cgit v1.2.3