[09_queue] concurrency, lock_free_queue, done.

This commit is contained in:
Liam Huang 2018-10-11 18:01:33 +08:00
parent e3cfa2cad9
commit ee3253afdd

View File

@ -0,0 +1,74 @@
/**
* Created by Liam Huang (Liam0205) on 2018/10/11.
*/
#ifndef QUEUE_LOCK_FREE_QUEUE_HPP_
#define QUEUE_LOCK_FREE_QUEUE_HPP_
#include <memory>
#include <atomic>
template <typename T>
class LockFreeQueue {
public:
using value_type = T;
private:
struct node {
std::shared<value_type> data = nullptr;
node* next = nullptr;
};
std::atomic<node*> head = nullptr;
std::atomic<node*> tail = nullptr;
public:
LockFreeQueue() head(new node), tail(head.load()) {}
LockFreeQueue(const LockFreeQueue&) = delete;
LockFreeQueue& operator=(const LockFreeQueue&) = delete;
// TODO(Liam Huang): move constructor and move assignment should be well implemented later,
// and hance marked "delete".
LockFreeQueue(LockFreeQueue&&) = delete;
LockFreeQueue& operator=(LockFreeQueue&&) = delete;
~LockFreeQueue() {
while (node* const old_head = head.load()) {
head.store(old_head->next);
delete old_head;
}
}
private:
node* pop_head() {
node* const res = head.load();
if (res == tail.load()) {
return nullptr;
}
head.store(res->next);
return res;
}
public:
bool empty() const {
return head.load() == tail.load();
}
std::shared_ptr<value_type> pop() {
node* old_head = pop_head();
if (nullptr == old_head) {
return nullptr;
} else {
auto res = old_head->data;
delete old_head;
return res;
}
}
void push(value_type new_value) {
auto new_data = std::make_shared<value_type>(new_value);
node* p = new node;
node* old_tail = tail.load();
old_tail->data.swap(new_data);
old_tail->next = p;
tail_.store(p);
}
};
#endif // QUEUE_LOCK_FREE_QUEUE_HPP_