]> AND Private Git Repository - loba.git/blob - sync_queue.h
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
Add a lock-free synchronized queue.
[loba.git] / sync_queue.h
1 #ifndef SYNC_QUEUE_H
2 #define SYNC_QUEUE_H
3
4 #if __GNUC__ == 4 && __GNUC_MINOR__ == 4
5 #  include <cstdatomic>         // <atomic> is named <cstdatomic> in gcc 4.4
6 #else
7 #  include <atomic>
8 #endif
9
10 template <typename T>
11 class sync_queue {
12 public:
13     sync_queue()
14     {
15         node* n = new node(NULL, NULL);
16         std::atomic_store(&head, n); // head.store(n);
17         std::atomic_store(&tail, n); // tail.store(n);
18     }
19
20     ~sync_queue()
21     {
22         node* n = head.load();
23         while (n != NULL) {
24             node* prev = n;
25             n = n->next;
26             delete prev;
27         }
28     }
29
30     bool empty() const
31     {
32         return head.load() == tail.load();
33     }
34
35     // size() is not not thread-safe
36     size_t size() const
37     {
38         size_t count = 0;
39         for (node* n = head.load()->next; n != NULL; n = n->next)
40             ++count;
41         return count;
42     }
43
44     bool push(const T& val)
45     {
46         node* old_tail = tail.load();
47         node* n = new node(val, NULL);
48         old_tail->next = n;
49         std::atomic_store(&tail, n); // tail.store(n);
50         return (old_tail == head.load());
51     }
52
53     bool try_pop(T& res)
54     {
55         node* old_head = head.load();
56         if (old_head == tail.load()) { // empty?
57             return false;
58         } else {
59             node* new_head = old_head->next;
60             std::atomic_store(&head, new_head); // head.store(new_head);
61             delete old_head;
62             res = new_head->value;
63             return true;
64         }
65     }
66
67 private:
68     struct node {
69         node(const T& v, node* n): value(v), next(n) { }
70         T value;
71         node* next;
72     };
73
74     std::atomic<node*> head;
75     std::atomic<node*> tail;
76 };
77
78 #endif // !SYNC_QUEUE_H
79
80 // Local variables:
81 // mode: c++
82 // End: