Можно ли проверить boost::lockfree::queue на заполнение?

#c #boost #queue #lock-free

#c #boost #очередь #без блокировки

Вопрос:

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

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

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

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

Ответ №1:

Похоже, что реализация Boost для 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 и смотрите, получите ли вы его или нет.

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

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

Комментарии:

1. Это был хорошо составленный ответ. Спасибо 🙂