Несколько возможностей:
- использовать флаг, который указывает, что продюсер завершен.Потребители, которые разблокируют семафор, должны проверить этот флаг и очистить его, когда он установлен.Когда производитель устанавливает флаг, он может сигнализировать семафору достаточно раз, чтобы освободить любых возможных потребителей.Вы должны позаботиться о состоянии гонки, когда что-то ставится в очередь для потребления, но флаг «проделано производителем» устанавливается до того, как потребитель пройдет проверку флага.Это может быть легко обработано, если вы позволите потребительским потокам идти вперед и попытаться удалить рабочий элемент из очереди, но они будут аккуратно обрабатывать ситуацию, когда ничего не нужно делать, даже если семафор был сигнализирован. Затем попросите их взглянуть на флаг «Выполнено производителем».
- используйте
pthread_kill()
для отправки сигнала ожидающим потребителям.Это должно вывести их из sem_wait()
, где они могут проверить код возврата EINTR
.Это также нужно будет тщательно кодировать, чтобы избежать гонок.Я не особенно знаком с обработкой сигналов POSIX, но я уверен, что он поставляется с собственным набором багажа, с которым вам нужно быть очень осторожным при правильной обработке. - переключитесь на использование условных переменных с мьютексами, где выможет удерживать состояние очереди и состояние готовности атомарно, удерживая мьютекс.
Конечно, как только это будет сделано, кто-то (поток производителя?) должен ждать очистки всех потоков-потребителей.- вероятно, сделав pthread_join()
для них - до того, как семафор будет разрушен / закрыт.
Параметр условной переменной, вероятно, является большим изменением, если у вас уже есть что-то, закодированное с использованием семафоров, и это может быть не такв нормальном случае, когда производятся и потребляются (возможно).Но могу поспорить, что легче рассуждать о возможных условиях гонки и правильно с ними обращаться.Обратите внимание, что я не говорю, что это легко, просто это может быть проще.