X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/loba.git/blobdiff_plain/4dc6e5f4f7bab0fa256fc11a74eddbac33d80f16..779b929d3831ca0aea2f667029d6381946c86e01:/sync_queue.h diff --git a/sync_queue.h b/sync_queue.h index 357a72d..c3f29e5 100644 --- a/sync_queue.h +++ b/sync_queue.h @@ -13,19 +13,21 @@ atomic<_Tp*>::store(_Tp* __v, memory_order __m) volatile # 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 +44,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