代码之家  ›  专栏  ›  技术社区  ›  uray

是否存在乐观的无锁FIFO队列实现?

  •  10
  • uray  · 技术社区  · 16 年前

    是否有C++的实现(源代码)? optmistic approach to lock-free FIFO queues" algorithm ?

    5 回复  |  直到 10 年前
        1
  •  11
  •   greyfade    16 年前

    Herb Sutter 在Dobbs博士的期刊上,他把这样一个队列作为有效一致性专栏的一部分。

    Writing Lock-Free Code: A Corrected Queue

        2
  •  4
  •   uray    16 年前

    我想总结一下作者给出的答案 ,基于 http://www.drdobbs.com/high-performance-computing/212201163 (本文的最后一部分),优化后的代码 (根据我的命名和编码惯例做了一些修改) :

    template <typename T> class LFQueue {
    private:
        struct LFQNode {
            LFQNode( T* val ) : value(val), next(nullptr) { }
            T* value;
            AtomicPtr<LFQNode> next;
            char pad[CACHE_LINE_SIZE - sizeof(T*) - sizeof(AtomicPtr<LFQNode>)];
        };
    
        char pad0[CACHE_LINE_SIZE];
        LFQNode* first;                 // for one consumer at a time
        char pad1[CACHE_LINE_SIZE - sizeof(LFQNode*)];
        InterlockedFlag consumerLock;   // shared among consumers
        char pad2[CACHE_LINE_SIZE - sizeof(InterlockedFlag)];
        LFQNode* last;                  // for one producer at a time
        char pad3[CACHE_LINE_SIZE - sizeof(LFQNode*)];
        InterlockedFlag producerLock;   // shared among producers
        char pad4[CACHE_LINE_SIZE - sizeof(InterlockedFlag)];
    public:
        LFQueue() {
            first = last = new LFQNode( nullptr ); // no more divider
            producerLock = consumerLock = false;
        }
    
        ~LFQueue() {
            while( first != nullptr ) {
                LFQNode* tmp = first;
                first = tmp->next;
                delete tmp;
            }
        }
    
        bool pop( T& result ) {
            while( consumerLock.set(true) ) 
            { }                             // acquire exclusivity
            if( first->next != nullptr ) {  // if queue is nonempty 
                LFQNode* oldFirst = first;
                first = first->next;
                T* value = first->value;    // take it out
                first->value = nullptr;     // of the Node
                consumerLock = false;       // release exclusivity
                result = *value;            // now copy it back
                delete value;               // and clean up
                delete oldFirst;            // both allocations
                return true;                // and report success
            }
            consumerLock = false;           // release exclusivity
            return false;                   // queue was empty
        }
    
        bool push( const T& t )  {
            LFQNode* tmp = new LFQNode( t );    // do work off to the side
            while( producerLock.set(true) ) 
            { }                             // acquire exclusivity
            last->next = tmp;               // A: publish the new item
            last = tmp;                     // B: not "last->next"
            producerLock = false;           // release exclusivity
            return true;
        }
    };
    

    `

        3
  •  1
  •   jaw    11 年前

    这是我实现的无锁FIFO。

    https://github.com/vovoid/vsxu/blob/master/engine/include/vsx_fifo.h

    vsx_fifo<my_struct, 512> my_fifo;
    

    my_struct my_struct_inst;
    ... fill it out ...
    while (!my_fifo.produce(my_struct_inst)) {}
    

    收件人:

    my_struct my_struct_recv;
    while(my_fifo.consume(my_struct_recv)) 
    { 
      ...do stuff...
    }
    
        4
  •  1
  •   Oktaheta    7 年前

    这个怎么样 lfqueue

    这是跨平台、无限排队线程的安全队列,已经过测试 多deq、多enq deq和多enq

    例如

    int* int_data;
    lfqueue_t my_queue;
    
    if (lfqueue_init(&my_queue) == -1)
        return -1;
    
    /** Wrap This scope in other threads **/
    int_data = (int*) malloc(sizeof(int));
    assert(int_data != NULL);
    *int_data = i++;
    /*Enqueue*/
     while (lfqueue_enq(&my_queue, int_data) == -1) {
        printf("ENQ Full ?\n");
    }
    
    /** Wrap This scope in other threads **/
    /*Dequeue*/
    while  ( (int_data = lfqueue_deq(&my_queue)) == NULL) {
        printf("DEQ EMPTY ..\n");
    }
    
    // printf("%d\n", *(int*) int_data );
    free(int_data);
    /** End **/
    
    lfqueue_destroy(&my_queue);
    
        5
  •  0
  •   Rick    16 年前