X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/loba.git/blobdiff_plain/4dc6e5f4f7bab0fa256fc11a74eddbac33d80f16..3634a92de5281a6b19ca03b49b21dad853f386b3:/sync_queue.h diff --git a/sync_queue.h b/sync_queue.h index 357a72d..fc35339 100644 --- a/sync_queue.h +++ b/sync_queue.h @@ -1,31 +1,23 @@ #ifndef SYNC_QUEUE_H #define SYNC_QUEUE_H -#if __GNUC__ == 4 && __GNUC_MINOR__ == 4 -# include // is named in gcc 4.4 +#include "atomic_compat.h" -template // fix missing definition in gcc 4.4 -void -atomic<_Tp*>::store(_Tp* __v, memory_order __m) volatile -{ atomic_address::store(__v, __m); } - -#else -# include -#endif +#define SYNC_QUEUE_BUFSIZE 16 template class sync_queue { public: sync_queue() { - node* n = new node(NULL); - head.store(n); - tail.store(n); + head_node = tail_node = new node(); + head.store(head_node->values); + tail.store(tail_node->values); } ~sync_queue() { - node* n = head.load(); + node* n = head_node; while (n != NULL) { node* prev = n; n = n->next; @@ -42,43 +34,65 @@ public: size_t size() const { size_t count = 0; - for (node* n = head.load()->next; n != NULL; n = n->next) - ++count; + if (head_node == tail_node) { + count = tail.load() - head.load(); + } else { + count = + (head_node->values + (SYNC_QUEUE_BUFSIZE - 1)) - head.load(); + for (node* n = head_node->next; n != tail_node; n = n->next) + count += SYNC_QUEUE_BUFSIZE; + count += tail.load() - tail_node->values; + } return count; } bool push(const T& val) { - node* old_tail = tail.load(); - node* n = new node(val); - old_tail->next = n; - tail.store(n); + T* old_tail = tail.load(); + T* new_tail; + if (old_tail == tail_node->values + (SYNC_QUEUE_BUFSIZE - 1)) { + tail_node->next = new node(); + tail_node = tail_node->next; + new_tail = tail_node->values; + } else { + new_tail = old_tail + 1; + } + *new_tail = val; + tail.store(new_tail); return (old_tail == head.load()); } bool try_pop(T& res) { - node* old_head = head.load(); - if (old_head == tail.load()) { // empty? + T* old_head = head.load(); + if (old_head == tail.load()) // empty? return false; + + T* new_head; + if (old_head == head_node->values + (SYNC_QUEUE_BUFSIZE - 1)) { + node* old_head_node = head_node; + head_node = head_node->next; + delete old_head_node; + new_head = head_node->values; } else { - node* new_head = old_head->next; - head.store(new_head); - delete old_head; - res = new_head->value; - return true; + new_head = old_head + 1; } + res = *new_head; + head.store(new_head); + return true; } private: struct node { - node(const T& v): value(v), next(NULL) { } - T value; + node(): next(NULL) { } + T values[SYNC_QUEUE_BUFSIZE]; node* next; }; - std::atomic head; - std::atomic tail; + node* head_node; + node* tail_node; + std::atomic head; + std::atomic tail; }; #endif // !SYNC_QUEUE_H