+#ifndef SYNC_QUEUE_H
+#define SYNC_QUEUE_H
+
+#if __GNUC__ == 4 && __GNUC_MINOR__ == 4
+# include <cstdatomic> // <atomic> is named <cstdatomic> in gcc 4.4
+#else
+# include <atomic>
+#endif
+
+template <typename T>
+class sync_queue {
+public:
+ sync_queue()
+ {
+ node* n = new node(NULL, NULL);
+ std::atomic_store(&head, n); // head.store(n);
+ std::atomic_store(&tail, n); // tail.store(n);
+ }
+
+ ~sync_queue()
+ {
+ node* n = head.load();
+ while (n != NULL) {
+ node* prev = n;
+ n = n->next;
+ delete prev;
+ }
+ }
+
+ bool empty() const
+ {
+ return head.load() == tail.load();
+ }
+
+ // size() is not not thread-safe
+ size_t size() const
+ {
+ size_t count = 0;
+ for (node* n = head.load()->next; n != NULL; n = n->next)
+ ++count;
+ return count;
+ }
+
+ bool push(const T& val)
+ {
+ node* old_tail = tail.load();
+ node* n = new node(val, NULL);
+ old_tail->next = n;
+ std::atomic_store(&tail, n); // tail.store(n);
+ return (old_tail == head.load());
+ }
+
+ bool try_pop(T& res)
+ {
+ node* old_head = head.load();
+ if (old_head == tail.load()) { // empty?
+ return false;
+ } else {
+ node* new_head = old_head->next;
+ std::atomic_store(&head, new_head); // head.store(new_head);
+ delete old_head;
+ res = new_head->value;
+ return true;
+ }
+ }
+
+private:
+ struct node {
+ node(const T& v, node* n): value(v), next(n) { }
+ T value;
+ node* next;
+ };
+
+ std::atomic<node*> head;
+ std::atomic<node*> tail;
+};
+
+#endif // !SYNC_QUEUE_H
+
+// Local variables:
+// mode: c++
+// End: