![]() |
Здравствуйте, гость ( Вход | Регистрация )
![]() ![]() |
![]() |
mezmay |
![]()
Сообщение
#1
|
![]() Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 272 Регистрация: 13.7.2009 Из: Ростов-на-Дону Пользователь №: 904 Спасибо сказали: 16 раз(а) Репутация: ![]() ![]() ![]() |
Наверное любой опытный программист сталкивался с задачей, когда надо использовать два рабочих буфера. Например обработка события получения данных - приняли массив данных, его надо обработать какой-то длительной процедурой и выдать без разрывов, к примеру, на выход звуковой платы. В такой ситуации могут использоваться два рабочих буфера - по принципу "один обрабатываем, второй воспроизводим. потом меняем местами". Вроде все просто, но я такое никогда не реализовывал. Подскажите, это правильно?:
Прошу прокомментировать данный пример. Понял ли я принцип? Сообщение отредактировал mezmay - 12.12.2012, 19:47 |
|
|
Iron Bug |
![]()
Сообщение
#2
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
в твоём примере нет параллельности. вероятно, воспроизведение должно быть запущено параллельно декодированию данных. иначе зачем вообще два буфера? или "асинхронная функция" подразумевает запуск в отдельном потоке?
вызов идёт через копирование объекта, то есть, гигантский массив будет копироваться при каждом вызове. иначе (если бы это была ссылка), следующая операция запортит объект. объекты создаются и разрушаются, передаются через стек, на это нужно время и реорганизация памяти. для быстрой работы логичнее выделить статический буфер. а его размер корректировать, при необходимости, но не каждый раз. и манипулировать указателями или ссылками. обычно делается два потока: на чтение и на запись. и мьютексы (ну или сигналы, если это Qt), которые сообщают о состоянии буферов. потоки ждут сигнала о (заполнении буфера) для чтения или освобождении буфера (для записи). регулирование этого дела зависит от особенностей конкретной задачи. Сообщение отредактировал Iron Bug - 12.12.2012, 19:58 |
|
|
mezmay |
![]()
Сообщение
#3
|
![]() Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 272 Регистрация: 13.7.2009 Из: Ростов-на-Дону Пользователь №: 904 Спасибо сказали: 16 раз(а) Репутация: ![]() ![]() ![]() |
Вопросизведение стартует в новом потоке и сразу начинается декодирование в данном потоке. То что манипулировать надо указателями - это понятно, здесь речь идет о принципе. Сообщение отредактировал mezmay - 12.12.2012, 20:01 |
|
|
Iron Bug |
![]()
Сообщение
#4
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
о принципе - это смотря чего ты хочешь добиться. у тебя в данном случае непрерывность воспроизведения не гарантирована: то есть, пока идёт декодирование какого-то количества данных, на выходе данные могут банально закончиться и будет пауза.
обычно для непрерывности всё-таки есть один кольцевой буфер и два потока оттуда читают и пишут, по необходимости. у меня, например, куча таких случаев на работе: с устройства идёт поток данных, драйвер его режет на куски и скармливает юзеру. есть две проблемы: чтобы буфер не переполнился и чтобы юзеру данные скармливались более-менее равномерно, без резких скачков и пауз. Сообщение отредактировал Iron Bug - 12.12.2012, 20:13 |
|
|
mezmay |
![]()
Сообщение
#5
|
![]() Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 272 Регистрация: 13.7.2009 Из: Ростов-на-Дону Пользователь №: 904 Спасибо сказали: 16 раз(а) Репутация: ![]() ![]() ![]() |
Цитата чтобы буфер не переполнился и чтобы юзеру данные скармливались более-менее равномерно Можно предельно простой пример этого? Цитата пока идёт декодирование какого-то количества данных, на выходе данные могут банально закончиться Ну тут уж ни какой алгоритм не гарантирует непрерывность
Сообщение отредактировал mezmay - 12.12.2012, 20:18 |
|
|
Iron Bug |
![]()
Сообщение
#6
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: ![]() ![]() ![]() |
я в таких случаях делаю два потока, кольцевой буфер и два указателя - на чтение и на запись. и два сигнала: об изменении указателя чтения и об изменении указателя записи. процесс, который пишет, получает данные, как-то их обрабатывает, и складывает в буфер, смещая указатель записи. и взводит сигнал о готовности. а процесс, который читает, ожидает сигнала (либо проверяет флаг), читает и смещает указатель чтения.
но кольцевой буфер - тот ещё геморрой, надо сказать. поэтому если есть его готовая реализация, то легче взять её. на самом деле, сигнал об изменении указателя чтения обычно не требуется. потому что в любом случае чтение должно быть шустрее, чем запись. иначе буфер будет переполняться и данные будут потеряны. и всё это должно быть сдобрено мьютексами для защиты обращения к указателям, чтобы одновременно не происходили запись и чтение оных, а то может получиться бардак. |
|
|
![]() ![]() ![]() |
![]() |
|
Текстовая версия | Сейчас: 14.5.2025, 11:04 |