Вы можете сделать это, но если вы действительно хотите, это другое дело - см. Другие сообщения.
Во-первых, забудьте обо всех пользовательских потоках, ожидающих общего семафора. Чтобы сделать то, что вы хотите, ожидающие потоки потребителя должны быть адресованы экземпляром. Чтобы сделать это, потребитель, который появляется, блокирует очередь и находит ее пустой, должен ждать своего собственного события. Кроме того, потребитель должен предоставить в своем вызове pop адрес того места, куда он хочет поместить объект. Таким образом, в дополнение к «нормальной» очереди объектов, потребительским потокам, которые должны ждать, нужна структура, содержащая указатель и событие для ожидания. Вы можете создать массив или циклический буфер из этих wait_structs при создании очереди P-C.
Тогда все готово.
ПРОИЗВОДИТЕЛЬ: (вызывает push с объектом ref / ptr)
Получает блокировку очереди и проверяет список wait_structs. Если есть запись, она загружает свой объект в адрес, на который указывает указатель wait_struct (то есть «отправка нового продукта () непосредственно в поток выполнения»), и сигнализирует о событии wait_struct. Если в списке wait_structs нет записи, производитель помещает свой объект в очередь объектов. Ах да - снимает блокировку очереди:)
ПОТРЕБИТЕЛЬ: (вызывает всплывающее окно с адресом, на который он хочет вернуть объект)
Получает блокировку очереди и проверяет счетчик очереди объектов. Если он не равен нулю, он выталкивает объект, помещает его в целевой адрес, который он предоставил, снимает блокировку и запускается. Если очередь объектов пуста, потребитель получает бесплатный wait_strut в списке wait_structs, устанавливает указатель на значение, которое он передал, снимает блокировку очереди и ожидает события. Когда событие получает сигнал, у потребителя уже есть свой объект (запущенный производителем), и он может просто продолжаться - не нужно снова посещать очередь ПК.
Да, этот дизайн работает (в любом случае в Delphi - должен работать в C ++) и быстрее, чем «классическая» основанная на семафорах ПК-очередь (которая быстрее, чем Windows Message Queue, которая быстрее очередь IOCP).
У меня это работает с таймаутом - я дам вам понять, как это сделать. (Подсказка - вы должны использовать местоположение объекта-потребителя (адресуемое переданным указателем) в качестве временного хранилища:)