#include #include #include #include #include template class queue { private: struct node { std::shared_ptr data; std::unique_ptr next; }; std::mutex head_mutex; std::unique_ptr head; std::mutex tail_mutex; node *tail; node *get_tail() { std::lock_guard tail_lock(tail_mutex); return tail; } std::unique_ptr pop_head() { std::lock_guard head_lock(head_mutex); if (head.get() == get_tail()) { return nullptr; } std::unique_ptr 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& other) = delete; queue& operator=(const queue& other) = delete; std::shared_ptr try_pop() { std::unique_ptr old_head = pop_head(); return old_head ? old_head->data : std::shared_ptr(); } void push(T new_value) { std::shared_ptr new_data( std::make_shared(std::move(new_value))); std::unique_ptr p(new node); node *const new_tail = p.get(); std::lock_guard tail_lock(tail_mutex); tail->data = new_data; tail->next = std::move(p); tail = new_tail; } }; void push(queue* q) { for (int i = 0; i < 10; ++i) { printf("pushing %d\n", i); q->push(i); } } void pop(queue* q) { int i = 0; while (true) { if (std::shared_ptr p = q->try_pop()) { printf("poping %d\n", *p); ++i; } if (i == 10) break; } } int main() { queue q; std::thread th1(push,&q); std::thread th2(pop,&q); th1.join(); th2.join(); return 0; }