Multithread queue atomic operations

后端 未结 2 451
刺人心
刺人心 2021-01-14 05:40

I\'m playing with the std::atomic structures and wrote this lock-free multi-producer multi-consumer queue, which I\'m attaching here. The idea for the queue is based on two

2条回答
  •  花落未央
    2021-01-14 06:19

    I believe I was able to crack this one. No livelock at 1000000 writes/reads for queues from size 2 to 1024 and from 1 producer and 1 consumer to 100 producers / 100 consumers.

    Here's the solution. The trick is not to use cell->m_next directly in the compare and swap (the same applies for the producer code by the way) and to require strict memory order rules:

    This seems to confirm my suspicion that it was compiler reordering of the reads writes. Here's the code:

    bool push(const TData& data)
    {
        CellNode* cell = m_produceHead.load(std::memory_order_acquire);
        if(cell == NULL)
            return false;
    
        while(!std::atomic_compare_exchange_strong_explicit(&m_produceHead,
                                                            &cell,
                                                            cell->m_next,
                                                            std::memory_order_acquire,
                                                            std::memory_order_release))
        {
            if(!cell)
                return false;
        }
    
        m_data[cell->m_idx] = data;
    
        CellNode* curHead = m_consumeHead;
        cell->m_next = curHead;
        while (!std::atomic_compare_exchange_strong_explicit(&m_consumeHead,
                                                             &curHead,
                                                             cell,
                                                             std::memory_order_acquire,
                                                             std::memory_order_release))
        {
            cell->m_next = curHead;
        }
    
        return true;
    }
    
    bool pop(TData& data)
    {
        CellNode* cell = m_consumeHead.load(std::memory_order_acquire);
        if(cell == NULL)
            return false;
    
        while(!std::atomic_compare_exchange_strong_explicit(&m_consumeHead,
                                                            &cell,
                                                            cell->m_next,
                                                            std::memory_order_acquire,
                                                            std::memory_order_release))
        {
            if(!cell)
                return false;
        }
    
        data = m_data[cell->m_idx];
    
        CellNode* curHead = m_produceHead;
        cell->m_next = curHead;
        while(!std::atomic_compare_exchange_strong_explicit(&m_produceHead,
                                                            &curHead,
                                                            cell,
                                                            std::memory_order_acquire,
                                                            std::memory_order_release))
        {
            cell->m_next = curHead;
        }
    
        return true;
    };
    

自定义标题
段落格式
字体
字号
代码语言
提交回复
热议问题