6 #ifndef LLU_ASYNC_QUEUE_H
7 #define LLU_ASYNC_QUEUE_H
9 #include <condition_variable>
13 namespace LLU::Async {
36 std::shared_ptr<value_type>
tryPop();
50 std::shared_ptr<value_type>
waitPop();
69 [[nodiscard]]
bool empty()
const;
74 std::shared_ptr<value_type> data;
75 std::unique_ptr<Node> next;
78 mutable std::mutex head_mutex;
79 std::unique_ptr<Node> head;
80 mutable std::mutex tail_mutex;
82 std::condition_variable data_cond;
84 const Node* getTail()
const {
85 std::lock_guard<std::mutex> tail_lock(tail_mutex);
89 std::unique_ptr<Node> popHead() {
90 std::unique_ptr<Node> old_head = std::move(head);
91 head = std::move(old_head->next);
95 std::unique_lock<std::mutex> waitForData() {
96 std::unique_lock<std::mutex> head_lock(head_mutex);
97 data_cond.wait(head_lock, [&] {
return head.get() != getTail(); });
101 std::unique_ptr<Node> waitPopHead() {
102 std::unique_lock<std::mutex> head_lock(waitForData());
106 std::unique_ptr<Node> waitPopHead(
value_type& value) {
107 std::unique_lock<std::mutex> head_lock(waitForData());
108 value = std::move(*head->data);
112 std::unique_ptr<Node> tryPopHead() {
113 std::lock_guard<std::mutex> head_lock(head_mutex);
114 if (head.get() == getTail()) {
115 return std::unique_ptr<Node>();
120 std::unique_ptr<Node> tryPopHead(
value_type& value) {
121 std::lock_guard<std::mutex> head_lock(head_mutex);
122 if (head.get() == getTail()) {
123 return std::unique_ptr<Node>();
125 value = std::move(*head->data);
132 std::shared_ptr<T> new_data(std::make_shared<T>(std::move(new_value)));
133 std::unique_ptr<Node> p(
new Node);
135 std::lock_guard<std::mutex> tail_lock(tail_mutex);
136 tail->data = new_data;
137 Node*
const new_tail = p.get();
138 tail->next = std::move(p);
141 data_cond.notify_one();
146 std::unique_ptr<Node>
const old_head = waitPopHead();
147 return old_head->data;
152 std::unique_ptr<Node>
const old_head = waitPopHead(value);
157 std::unique_ptr<Node>
const old_head = tryPopHead();
158 return old_head ? old_head->data : std::shared_ptr<T>();
163 std::unique_ptr<Node>
const old_head = tryPopHead(value);
164 return static_cast<bool>(old_head);
169 std::lock_guard<std::mutex> head_lock(head_mutex);
170 return (head.get() == getTail());
173 #endif // LLU_ASYNC_QUEUE_H