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