Simple threading facilities for C++, inspired by the book by Williams
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

67 lines
1.2 KiB

#pragma once
/* Thread safe queue (with fine grain locks).
Based on the book by Williams.
No wait_and_pop.
*/
#include <memory>
#include <thread>
template <typename T>
class queue {
private:
struct node {
std::shared_ptr<T> data;
std::unique_ptr<node> next;
};
std::mutex head_mutex;
std::unique_ptr<node> head;
std::mutex tail_mutex;
node* tail;
node* get_tail(){
std::lock_guard<std::mutex> lock(tail_mutex);
return tail;
}
std::unique_ptr<node> pop_head(){
std::lock_guard<std::mutex> lock(head_mutex);
if(head.get() == get_tail()){
return nullptr;
}
std::unique_ptr<node> old_head = std::move(head);
head = std::move(old_head->next);
return old_head;
}
public:
queue()
: head(new node)
, tail(head.get())
{}
queue(const queue &) = delete;
queue& operator=(const queue &) = delete;
std::shared_ptr<T> try_pop(){
std::unique_ptr<node> old_head = pop_head();
return old_head ? old_head->data : nullptr;
}
void push(T value){
auto new_data = std::make_shared<T>(std::move(value));
std::unique_ptr<node> p(new node);
node* const new_tail = p.get();
std::lock_guard<std::mutex> lock(tail_mutex);
tail->data = new_data;
tail->next = std::move(p);
tail = new_tail;
}
};