Как понять вызов Compare_exchange_strong с std :: memory_order_acquire - PullRequest
1 голос
/ 16 апреля 2019

Цитируется из C ++ Параллелизм в действии 7.2.5-Применение модели памяти к стеку без блокировки.

Следующий код цитируется в книге. И я знаю, что это нормально, когда есть только одна популярная тема. Но если есть два всплывающих потока, без правила о последовательности выпуска, можно ли безопасно использовать memory_order_acquire.

Насколько мне известно, мне нужно заменить memory_order_acquire на memory_order_acq_rel, что приведет к синхронизации между двумя потоками pop. Но в книге сказано, что memory_order_acquire достаточно.

Неужели мое понимание memory_order_acquire неверно: сбор и выпуск не должны быть сопряжены ?

template<typename T>
class lock_free_stack
{
    void increase_head_count(counted_node_ptr& old_counter)
    {
        counted_node_ptr new_counter;
        do
        {
            new_counter=old_counter;
            ++new_counter.external_count;
        }

        // problem here
        while(!head.compare_exchange_strong(old_counter,new_counter
            ,std::memory_order_acquire,std::memory_order_relaxed));

        old_counter.external_count=new_counter.external_count;
    }

    std::shared_ptr<T> pop()
    {
        counted_node_ptr old_head=head.load();
        for(;;)
        {
            // call
            increase_head_count(old_head);

            node* const ptr=old_head.ptr;
            if(!ptr)
            {
                 return std::shared_ptr<T>();
            }
            if(head.compare_exchange_strong(old_head,ptr->next))
            {
                 // todo delete
            }
            else if(ptr->internal_count.fetch_sub(1)==1)
            {
                delete ptr;
            }
        }
    }
}
...