1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
   | #ifndef LOCK_FREE_QUEUE_HPP
#define LOCK_FREE_QUEUE_HPP
 
#include <atomic>
 
// Note : implementation is from
// http://www.drdobbs.com/parallel/writing-lock-free-code-a-corrected-queue/210604448
 
template<typename T>
class lock_free_queue
{
    struct node
    {
        node() : next(nullptr) {}
        node(const T& t) : data(t), next(nullptr) {}
 
        T     data;
        node* next;
    };
 
    node* first;
    std::atomic<node*> dummy, last;
 
public :
 
    lock_free_queue() {
        // Always keep a dummy separator between head and tail
        first = last = dummy = new node();
    }
 
    ~lock_free_queue() {
        // Clear the whole queue
        while (first != nullptr)
        {
            node* temp = first;
            first = temp->next;
            delete temp;
        }
    }
 
    // Disable copy
    lock_free_queue(const lock_free_queue& q) = delete;
    lock_free_queue& operator = (const lock_free_queue& q) = delete;
 
    // To be called by the 'producer' thread
    void push(const T& t) {
        // Add the new item to the queue
        (*last).next = new node(t);
        last = (*last).next;
 
        // Clear consumed items
        while (first != dummy)
        {
            node* temp = first;
            first = temp->next;
            delete temp;
        }
    }
 
    // To be called by the 'consumer' thread
    bool pop(T& t) {
        // Return false if queue is empty
        if (dummy != last)
        {
            // Consume the value
            t = (*dummy).next->data;
            dummy = (*dummy).next;
            return true;
        }
        else
            return false;
    }
 
    // To be called by the 'consumer' thread
    bool empty() const {
        return dummy == last;
    }
 
    // This method should not be used in concurrent situations
    void clear() {
        while (first != dummy)
        {
            node* temp = first;
            first = temp->next;
            delete temp;
        }
 
        first = dummy.load();
 
        while (first->next != nullptr)
        {
            node* temp = first;
            first = temp->next;
            delete temp;
        }
 
        last = dummy = first;
    }
};
 
#endif | 
Partager