У меня есть push-фильтр DirectShow, написанный на Delphi 6 с использованием библиотеки компонентов DSPACK.Я реализую стратегию блокировки для вызова FillBuffer () фильтра принудительного исходного кода.Фильтр push-источника принимает аудиоданные в один или несколько буферов, хранящихся в наборе буферов.Каждый метод в коллекции буферов защищен критическим разделом.
Каждый буфер в коллекции получает данные из другого источника, и каждый источник имеет свой собственный поток.Вызов FillBuffer () блокируется до тех пор, пока в каждом буфере коллекции не будет достаточно данных, чтобы удовлетворить объем данных, который FillBuffer () попросил предоставить, поскольку данные смешиваются вместе, образуя объединенный буфер, который возвращается вызывающей стороне.
Вот стратегия, которую я разработал, чтобы избежать условий гонки и тупиков.В коллекции буферного хранилища есть метод с именем isEnoughData () , который делает это:
- Получает тот же критический раздел, который защищает все другие методы в коллекции.
- Выполняет итерацию каждой проверки буфера, чтобы увидеть, достаточно ли в каждом буфере данных для удовлетворения текущего запроса.
- Если данных достаточно, возвращается ИСТИНА
- Если есть , а не Достаточно данных, он получает Mutex , используемый для облегчения блокировки, и возвращает FALSE и сохраняет количество запрошенных байтов, которые не могут быть заполнены в FNumPendingBytesRequested.
- Перед возвратом освобождает критический разделcourse.
FillBuffer () выполняет следующие действия:
- Вызывает isEnoughData ()
- Если возвращено значение TRUE, возвращается смешанный (объединенный буфер)данные для вызывающего абонента в предоставленном образце .
- Если FALSE, он выполняет WaitForSingleObject () для Mutex , который был получен коллективомво время вызова isEnoughData () , как описано выше, блокируя его до тех пор, пока не появится достаточно данных.Когда он получает Mutex , он берет данные из коллекции и возвращает их вызывающей стороне, а затем выпускает Mutex .
Все методыв коллекции хранилища, которая добавляет данные в любой буфер в проверке коллекции, чтобы проверить, может ли FNumPendingBytesRequested быть удовлетворен перед возвратом.Если это так, то Mutex освобождается, тем самым разблокируя вызов FillBuffer (), который затем захватывает данные и возвращает их.Естественно, коллекция выпускает Mutex , когда она уничтожена.
Это кажется мне пуленепробиваемым.Я считаю, что он адекватно защищает от состояния гонки между вызовом FillBuffer () для isEnoughData () и другими потоками, добавляющими данные в коллекцию.Я также не вижу мест, где может возникнуть состояние гонки или тупик.Я прав в этом?Любые советы или предостережения в отношении стратегии также приветствуются.
Большой вопрос : Единственная потенциальная проблема, которую я вижу, это если другой поток добавляет достаточно данных для выпуска Mutex до того, как FillBuffer () сможет вызвать WaitForSingleObject () и заблокировать.Но я понимаю, что вызов WaitForSingleObject () для синхронизируемого объекта, который не принадлежит никому, немедленно возвращается с владением объектом, поэтому это не должно быть проблемой, поскольку это означает, что необходимые данные теперь доступны.Правильно ли мое понимание?