Я думаю, вам понадобится что-то более сложное, чтобы достичь цели по надежности.
Мое понимание вашей проблемы состоит в том, что у вас есть один производитель и неизвестное количество потребителей, которые все являются разными процессами. Каждый потребитель НИКОГДА не может пропустить ни одного события.
Я хотел бы получить больше разъяснений относительно того, что означает пропущенное событие.
i) если потребитель начал работать и добрался до того, как он дождался вашего метода уведомления и произошло событие, должен ли он обработать его, даже если он не был полностью готов в момент отправки уведомления? (то есть когда потребитель считается активным? когда он запускается или когда обрабатывает свое первое событие)
ii) аналогично, если потребитель обрабатывает событие, а код, ожидающий следующего уведомления, еще не начал свое ожидание (я предполагаю структуру кода Wait -> Process -> Loop to Wait
), тогда он должен знать, что произошло другое событие пока он зацикливался?
Я бы предположил, что i) «не совсем», так как это гонка между запуском процесса и «готовностью», и ii) «да»; то есть уведомления, по сути, ставятся в очередь для каждого потребителя, как только он присутствует, и каждый потребитель получает возможность использовать все события, которые создаются, пока он активен и не может их пропустить.
Итак, что вам нужно, так это возможность отправлять поток уведомлений группе потребителей, где потребитель гарантированно действует на все уведомления в этом потоке от точки, в которой он действует первым, до точки, где оно отключается т.е. если производитель создает следующий поток уведомлений
1 2 3 4 5 6 7 8 9 0
и потребитель а) запускается и обрабатывает 3, он также должен обрабатывать 4-0
если потребитель b) запускается и обрабатывает 5, но выключается после 9, то он должен был обработать 5,6,7,8,9
если потребитель c) работал, когда начались уведомления, он должен был обработать 1-0
и т.д.
Просто пульсировать событие не получится. Если потребитель не ожидает активно события, когда событие пульсирует, то он пропустит событие, поэтому мы потерпим неудачу, если события генерируются быстрее, чем мы можем повторить цикл ожидания следующего события.
Использование семафора также не будет работать так, как если бы один потребитель работал быстрее, чем другой, до такой степени, что он может вернуться к вызову семафора до того, как другой завершит обработку, и если в это время появится другое уведомление, тогда один потребитель может обработать событие не раз, и можно было пропустить один. То есть вы можете выпустить 3 потока (если производитель знает, что есть 3 потребителя), но вы не можете гарантировать, что каждый потребитель будет выпущен только один раз.
Кольцевой буфер событий (количество тиков) в разделяемой памяти, при котором каждый потребитель знает значение события, которое он обработал в последний раз, а потребители получают оповещения через импульсное событие, должен работать за счет того, что некоторые потребители не синхронизированы с клещи иногда; то есть, если они пропустят один, они поймают в следующий раз, когда им пульсируют. Пока кольцевой буфер достаточно велик, чтобы все потребители могли обрабатывать события до того, как производитель зацикливается в буфере, у вас должно быть все в порядке.
В приведенном выше примере, если потребитель d пропускает импульс для события 4, потому что он не ожидал своего события в то время, а затем переходит в ожидание, он будет разбужен при возникновении события 5 и с момента его последней обработки считается 3, он обработает 4 и 5, а затем вернется к событию ...
Если этого недостаточно, я бы предложил что-то вроде PGM через сокеты, чтобы дать вам надежную многоадресную рассылку; Преимущество этого состоит в том, что вы можете перевести своих потребителей на разные машины ...