Эта стратегия синхронизации потоков Windows для моего push-фильтра DirectShow (достаточно) пуленепробиваема? - PullRequest
0 голосов
/ 21 ноября 2011

У меня есть push-фильтр DirectShow, написанный на Delphi 6 с использованием библиотеки компонентов DSPACK.Я реализую стратегию блокировки для вызова FillBuffer () фильтра принудительного исходного кода.Фильтр push-источника принимает аудиоданные в один или несколько буферов, хранящихся в наборе буферов.Каждый метод в коллекции буферов защищен критическим разделом.

Каждый буфер в коллекции получает данные из другого источника, и каждый источник имеет свой собственный поток.Вызов FillBuffer () блокируется до тех пор, пока в каждом буфере коллекции не будет достаточно данных, чтобы удовлетворить объем данных, который FillBuffer () попросил предоставить, поскольку данные смешиваются вместе, образуя объединенный буфер, который возвращается вызывающей стороне.

Вот стратегия, которую я разработал, чтобы избежать условий гонки и тупиков.В коллекции буферного хранилища есть метод с именем isEnoughData () , который делает это:

  1. Получает тот же критический раздел, который защищает все другие методы в коллекции.
  2. Выполняет итерацию каждой проверки буфера, чтобы увидеть, достаточно ли в каждом буфере данных для удовлетворения текущего запроса.
  3. Если данных достаточно, возвращается ИСТИНА
  4. Если есть , а не Достаточно данных, он получает Mutex , используемый для облегчения блокировки, и возвращает FALSE и сохраняет количество запрошенных байтов, которые не могут быть заполнены в FNumPendingBytesRequested.
  5. Перед возвратом освобождает критический разделcourse.

FillBuffer () выполняет следующие действия:

  1. Вызывает isEnoughData ()
  2. Если возвращено значение TRUE, возвращается смешанный (объединенный буфер)данные для вызывающего абонента в предоставленном образце .
  3. Если FALSE, он выполняет WaitForSingleObject () для Mutex , который был получен коллективомво время вызова isEnoughData () , как описано выше, блокируя его до тех пор, пока не появится достаточно данных.Когда он получает Mutex , он берет данные из коллекции и возвращает их вызывающей стороне, а затем выпускает Mutex .

Все методыв коллекции хранилища, которая добавляет данные в любой буфер в проверке коллекции, чтобы проверить, может ли FNumPendingBytesRequested быть удовлетворен перед возвратом.Если это так, то Mutex освобождается, тем самым разблокируя вызов FillBuffer (), который затем захватывает данные и возвращает их.Естественно, коллекция выпускает Mutex , когда она уничтожена.

Это кажется мне пуленепробиваемым.Я считаю, что он адекватно защищает от состояния гонки между вызовом FillBuffer () для isEnoughData () и другими потоками, добавляющими данные в коллекцию.Я также не вижу мест, где может возникнуть состояние гонки или тупик.Я прав в этом?Любые советы или предостережения в отношении стратегии также приветствуются.

Большой вопрос : Единственная потенциальная проблема, которую я вижу, это если другой поток добавляет достаточно данных для выпуска Mutex до того, как FillBuffer () сможет вызвать WaitForSingleObject () и заблокировать.Но я понимаю, что вызов WaitForSingleObject () для синхронизируемого объекта, который не принадлежит никому, немедленно возвращается с владением объектом, поэтому это не должно быть проблемой, поскольку это означает, что необходимые данные теперь доступны.Правильно ли мое понимание?

...