Если ptr
равно std::atomic<int*>
, ++ptr
или ptr++
или ptr.fetch_add(1, std::memory_order_acq_rel)
, убедитесь, что ни одна из предшествующих / последующих загрузок / хранилищ не будет переупорядочена после / до этой операции.
++ptr
или ptr++
по существу ptr.fetch_add(1, std::memory_order_seq_cst)
, а std::memory_order_seq_cst
почти всегда является избыточным убийством (не может привести пример, где это не так).
Еще более эффективный одноместный считыватель:
int arr[some_constexpr];
std::atomic<int*> ptr;
int* p = ptr.load(std::memory_order_acquire);
int element = *p;
ptr.store(p + 1, memory_order_release);
В основном выше описан способ реализации boost::lockfree::spsc_queue
.
В качестве примечания, boost::lockfree::spsc_queue
является истинной без ожидания (самая сильная неблокирующая гарантия прогресса) очереди. Операции push
/ pop
- это загрузка 1 relaxed
, загрузка 1 acquire
и хранение 1 release
, и принципиально невозможно реализовать очередь одного производителя-одного потребителя быстрее, чем эта (без дефекты реализации) с гарантией заказа FIFO. Он часто используется в качестве теста для всех остальных очередей . Вы можете посмотреть на это.