2013-04-02 5 views
0

У меня есть приложение аудио dsp, которое производит выход со значительно более высокой скоростью, чем в режиме реального времени, используя пул потоков. Это предназначено для использования в играх, и звук должен быть потоковым с довольно низкой задержкой. Каждый готовый буфер заканчивается в основной миксерной нити, из которой мне нужно доставить его программисту приложений. Я решил, что у меня может быть метод read_samples в основном классе, который берет указатель буфера и количество образцов для чтения и возвращает количество фактически прочитанных образцов.Эффективное использование fifo для приложения для потоковой передачи звука

Я смотрю на блокировку free fifo, а именно одиночную очередь производителей/отдельных потребителей от boost.lockfree. Мои текущие цели проекта заключаются в следующем:

  1. Важно, что данные выталкивается в и из ФИФО очень быстро, так что мы хотим, как несколько блокирующих операций, как это возможно. В большинстве случаев программисты приложений, вероятно, будут вызывать метод read_samples основного класса внутри потока приоритета уровня прерывания, так как многие подсистемы аудио-ввода-вывода получают данные таким образом (например, через обратный вызов). Таким образом, мы приходим к пунктам 2 и 3.

  2. Если read_samples вызывается и не хватает образцов в ФИФО, чтобы доставить требуемую сумму, мы, вероятно, следует принять то, что мы имеем (если что-нибудь), а затем немедленно возвращайтесь без блокировки. Если мы заблокируем и подождем, , мы можем повлиять на многие другие аудиовоспроизведения, за которые может отвечать уровень прерывания .

  3. Если производитель пытается записать в полный буфер, мы хотим подождать до , все образцы были написаны. Мы хотим, чтобы пользователь читал, пока мы делаем , ожидая записи, чтобы они могли очистить пространство в буфере для нас. Для продюсера не стоит ждать, так что части не нужно блокировать. Установив размер кольцевого буфера, который примерно соответствует нашим ожиданиям латентности, мы можем убедиться, что производитель дает нам всего достаточное количество данных, чтобы избежать остановки воспроизведения, но не более того.

Точки один и два тривиальны для фактического осуществления, при условии, что мои проектные решения с точки зрения того, когда и когда не блокировать, кажутся разумными. Это третий вопрос, который дает мне немного неприятностей. Есть ли эффективный способ блокировки до тех пор, пока буфер больше не будет заполнен, и просыпаться, только когда мы сможем написать ? Я могу легко определить размер буфера, и это, к счастью, атомная операция. Но как блокировать и разблокировать меня, так как мы хотим, чтобы блокировать блокировку преждевременно, если пришло время закрыться, например. Что я использую для этого? Переменная состояния? Если это так, я был бы очень благодарен, если бы кто-нибудь мог предложить какой-нибудь псевдокод. Я понимаю, как использовать барьеры, но пока не смотрел в переменных состояния, и я не уверен, что их понимаю. Тем более, что они, по-видимому, могут проснуться без выполнения условия, что кажется странным. Любые предложения будут высоко оценены.

+0

Должны ли быть фактические данные в FIFO? В высокопроизводительных вводах-выводах чаще всего создается очередь указателей на «пустые» буферы, доступные для драйвера.Драйвер заполняет буфер (или частичный буфер и длину), с данными, очереди с указателя буфера на более высокий уровень и сразу же выделяет другой указатель буфера для следующей партии данных. Драйвер сигнализирует семафор каждый раз, когда он очереди назад, так что поток более высокого уровня знает, что есть один для удаления и обработки. –

+0

«Важно, чтобы данные быстро и быстро вставлялись и выходили из fifo» - тривиально для проектирования/использования очереди, которая не требует жесткой блокировки вообще, пока есть только один производитель, один потребитель, и вы только очереди указатели. –

+0

Спасибо за советы, Мартин. Нажатие указателей на буферы в fifo - хорошая идея, что мне придется заглянуть. Я действительно решил свою исходную проблему, используя переменную условия (я, наконец, понял, как правильно их использовать). Так что теперь производитель ждет терпеливо для потребителя, как я и предполагал. –

ответ

0

Правильный способ получить поведение блокировки, когда производитель произвел слишком много материала, имеет переменную условия. Производитель вызывает ожидания, когда он достиг своего предела, и потребитель затем вызывает notify_all, как только он потребляет некоторые данные. Затем продюсер просыпается и генерирует больше и т. Д.

Смежные вопросы