Можно ли проверить полный буст :: lockfree :: queue? - PullRequest
0 голосов
/ 28 марта 2019

Я использую boost :: lockfree :: queue Foo (128).

Перед отправкой очереди я могу проверить очередь на пустое состояние с помощью функции Foo.empty().

IИнтересно, могу ли я так же проверить его статус на полную мощность, прежде чем нажать!Не удалось найти ни одного ресурса в Интернете, объясняющего, как это сделать.

Есть предложения?

1 Ответ

1 голос
/ 29 марта 2019

Похоже, что реализация Boost's LF для нескольких производителей queue не поддерживает это. Другие очереди MPMC могут.

boost::lockfree::spsc_queue (очередь кольцевого буфера с одним потребителем для одного производителя) с spsc.write_available() > 0.


boost::lockfree::queue не является фиксированным размером по умолчанию , только если вы передаете емкость в качестве аргумента шаблона или fixed_sized<true>. Если структура данных настроена как фиксированная по размеру, внутренние узлы хранятся внутри массива и адресуются с помощью индексации массива. (Но это не кольцевой буфер, как некоторые другие очереди MPMC.) В противном случае они динамически распределяются и хранятся в свободном списке.

Для производительности вы, вероятно, должны сделать его фиксированного размера. Или, если вы хотите ограничить динамическое выделение, вы можете использовать bounded_push вместо push, поэтому он вернет false вместо перехода к ОС для получения дополнительной памяти (которая может быть не без блокировки).


Если вы используете queue<fixed_size<true>>, то возможно для заполнения очереди.

Но проверять отдельно не имеет смысла, потому что другой производитель мог бы заполнить очередь между проверкой и отправкой . Вы ищете оптимизацию производительности, например, избегаете конструирования объекта, если очередь, вероятно, будет заполнена к тому времени, когда вы будете готовы вызвать push?

(Кроме того, потребитель может сделать очередь незаполненной сразу после проверки, поэтому на самом деле имеет смысл проверять только как часть предпринятой попытки. И, возможно, даже нет эффективного способа проверки без блокировки В противном случае они могли бы иметь функцию, всегда возвращающую true для очередей нефиксированного размера, и возвращающие значимый результат для фиксированного размера.)

Вот почему push() возвращает bool: false означает, что очередь была заполнена (или не удалось выделить новый узел для очередей нефиксированного размера).


Перед отправкой в ​​очередь я могу проверить очередь на пустое состояние с помощью функции Foo.empty().

Надеюсь, вы на самом деле не делаете этого; у него все те же проблемы гонок с другими потоками, как у push, и с меньшими возможностями для оптимизации. Перед попыткой нет объекта, который нужно создать, просто позвоните pop и посмотрите, получите ли вы его или нет.

Другой поток мог сделать очередь пустой или сделать ее непустой между вашей проверкой и вашим фактическим всплывающим списком. Если вы не единственный потребитель, в этом случае видение непустого означает, что вы можете определенно всплывать. Случай использования одного производителя для нескольких производителей не будет совместим с spsc_queue.

В любом случае, именно поэтому bool pop(T &); не T pop().

...