Вы можете попросить поток чтения периодически проверять размер очереди (например, каждые 1000 элементов) и публиковать std::atomic<int> qsize
(с хранилищем mo_relaxed
), которое может прочитать 3-й поток.
Используйте неатомарный счетчик, который закрыт для читателя.Читатель уменьшает его и сбрасывает до 1000+ публикует, когда он достигает нуля.Храните его в строке кэша, к которой писатель не прикасается, так что никакой дополнительной конкуренции вообще не возникает, за исключением каждого 1000-го элемента, который вы делаете в хранилище, для которого требуется RFO, прежде чем оно сможет передать значение в строку кэша.Но это хранилище только для записи, а не RMW, поэтому буфер хранилища может скрыть задержку.(За исключением x86, где следующий атомарный RMW всегда является полным барьером, поэтому ему придется ждать, пока это хранилище будет зафиксировано. Но это только каждые 1000 операций удаления очереди, поэтому он едва замедлит работу считывателя.)
Имея std::atomic<int>
, что и читатель, и писатель атомарно inc / dec заставят их конкурировать друг с другом больше, чем очередь SPSC.Не так плохо, как борьба за блокировку, но я ожидаю, что это будет намного хуже, чем я предлагал.
Детали того, что происходит, могут зависеть от сгенерированного компилятором asm дляцелевая машина, и какое изменение порядка выполнения она может сделать.Я не знаю, но если в документах говорится, что это не поддерживается, вам придется исследовать или экспериментировать, если вы хотите рисковать.
Предположительно, звоните read_available()
, когда читатель находится в середине.отказ от элемента по какой-то причине небезопасен.
Вы должны взглянуть на реализацию, чтобы увидеть, означает ли это, что потенциал просто отбрасывается одним или полным мусором.