Вкратце, событие ручного сброса — это конструкция синхронизации, которая находится либо в «сигнальном», либо в «несигнальном» состоянии. В сигнальном состоянии любой поток, который вызывает функцию ожидания для события не будет блокироваться, и выполнение продолжится без изменений. Все без исключения потоки, вызывающие функцию ожидания для несигнального объекта, будут блокироваться до тех пор, пока событие не войдет в сигнальное состояние.
Переход между сигнальным и несигнальным состояниями происходит только в результате явных вызовов таких функций, как SetEvent и Сбросить событие.
Я создал механизм синхронизации в Windows, который использует как эти события ручного сброса, так и их братьев и сестер с автоматическим сбросом. Механизм автоматического сброса можно легко воспроизвести с помощью семафора, но я изо всех сил пытаюсь найти эквивалент для разновидности ручного сброса.
В частности, хотя условная переменная с функцией «уведомить всех» может показаться на первый взгляд похожей, она ведет себя значительно иначе (возможно, нефункционально), если принять во внимание тот факт, что для нее требуется связанный мьютекс. Во-первых, прежде чем поток сможет ждать в условной переменной, он должен получить соответствующий мьютекс. В дополнение к затратам на получение и освобождение мьютекса это излишне сериализует все потоки, которые собираются ждать. При пробуждении, даже если все потоки уведомлены, только один поток фактически получит мьютекс за раз, что приведет к дополнительным потерям производительности и параллелизма, поскольку в этом случае мьютекс не служит никакой цели.
Случай с выпуском особенно плох в многопроцессорной системе, учитывая, что одновременный выпуск всех ожидающих гарантирует, что разница между condvar и событием Windows будет заметна - с событием в N потоков станет доступным для выполнения в системе с N ЦП. , и могут работать параллельно, в то время как с condvar — даже с реализацией, которая избегает громоподобного стада — потоки могут просачиваться только по одному через связанный мьютекс.
Будем очень признательны за любые указатели на конструкцию, которая лучше имитирует поведение событий ручного сброса. Самое близкое, что я могу найти, - это барьер - это позволяет несинхронизированный подход и выпуск нескольких потоков к барьеру, но барьер "ломается" на основе количества ожидающих потоков, а не явного вызова приложения, что мне и нужно.