Реализация one-to-many producer-consumer очереди для кроссплатформенного приложения на С-C++

в 13:26, , рубрики: Песочница, метки: , ,

В многопоточных приложениях иногда возникает необходимость создать producer/consumer очередь. Наилучший вариант это использовать для этого готовую библиотеку. Если по каким-то причинам этого сделать нельзя, то такую очередь можно реализовать самому. Как правило, для этого используются механизмы синхронизации mutex и condition variables.

Интерфейс синхронизации различается от среды к среде, поэтому приходится либо писать высокоуровневую обертку, либо брать за основу интерфейс какой-то среды и реализовать его для других. К примеру, можно взять за основу интерфейс pthread, и для Windows реализовать функции pthread_mutex_* и pthread_cond_*, на основе которых уже построить очередь.

Существует более легкий способ. Он заключается в том что можно создать сокет пару (socketpair) или трубу (pipe) из двух связанных дескрипторов, отдать пишущий конец трубы поставщику (producer), а читающий конец отдать всем потребителям (consumers). Если задача определена как структура фиксированной длины, то поставщик простой записью в пишущий дескриптор добавляет задачу в очередь. Потребители висят в блокирующем чтении на читающем дескрипторе. При появлении данных в трубе только один потребитель проснется и прочтет задачу.

Таким образом, используется готовый механизм синхронизации внутри ядра. Интерфейс pipe() есть практически в любой среде. В UNIX есть также socketpair(), легко реализуемый под WIndows.

Если очередь переполнена, то поставщик заблокируется в write() (или send() для сокетов). Если блокировка нежелательна, можно пишущий дескриптор перевести в неблокирующий режим.

Таким образом pipe или socketpair — это удобное кроссплатформенное решение для producer/consumer очереди в многопоточном или многопроцессном приложении, использующее готовые механизмы синхронизации в ядре.


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js