2010-03-10 2 views
11

Я пишу приложение, которое должно использовать большие звуковые мультисэмплы, обычно размером около 50 мб. Один файл содержит около 80 отдельных коротких звуковых записей, которые могут быть воспроизведены в моем приложении в любое время. По этой причине все аудиоданные загружаются в память для быстрого доступа.Как выполнить кросс-платформенный асинхронный ввод-вывод файлов в C++

Однако при загрузке одного из этих файлов в память может потребоваться много секунд, потому что мне нужно прочитать большой объем данных с помощью ifstream, то есть мой программный графический интерфейс временно заморожен. Я попытался сопоставить память с моим файлом, но это вызывает огромные всплески процессора и беспорядок звука каждый раз, когда мне нужно перейти в другую область файла, что неприемлемо.

Так что это заставило меня думать, что выполнение чтения асинхронного файла решит мою проблему, то есть данные будут прочитаны в другом процессе и вызовет функцию при завершении. Это должно быть совместимо для Mac OS X и Windows и на C++.

EDIT: Не хотите использовать библиотеку Boost, потому что я хочу сохранить небольшую базу кода.

+0

re: Boost.asio, он также существует как отдельная версия, см. Http://think-async.com/ – Hasturkun

+0

Вы также можете читать свои данные в небольших кусках, которые не занимают столько времени, а затем позволяют цикл событий выполняется между ними. – kashiraja

ответ

8

boost имеет библиотеку asio, которую я раньше не использовал (это не список одобренных сторонних библиотек NASA).

Мой собственный подход состоял в том, чтобы написать код чтения файла дважды, один раз для Windows, один раз для API POSIX aio, а затем просто выбрать подходящий для связи.

Для Windows используйте OVERLAPPED (вы должны включить его в вызове CreateFile, а затем пропустите структуру OVERLAPPED при чтении). Вы можете либо установить событие при завершении (ReadFile), либо вызвать обратный вызов завершения (ReadFileEx). Вероятно, вам нужно будет изменить основной цикл событий, чтобы использовать MsgWaitForMultipleObjectsEx, чтобы вы могли либо ждать событий ввода-вывода, либо разрешать обратные вызовы в дополнение к получению сообщений в окне WM_. MSDN имеет документацию для этих функций.

Для Linux есть либо fadvise, и epoll, которые будут использовать кеш readahead, или aio_read, которые позволят выполнять текущие запросы чтения async. После завершения запроса вы получите сигнал, который вы должны использовать для публикации сообщения XWindows и пробуждения цикла обработки событий.

Оба варианта немного отличаются друг от друга, но сетевой эффект один и тот же - вы запрашиваете чтение, которое завершается в фоновом режиме, после чего заканчивается цикл отправки событий, когда заканчивается ввод-вывод.

+0

Да, мне пришлось написать пару вещей два раза раньше, один для Windows для POSIX, так что это не проблема. Где я могу пойти, чтобы прочитать асинхронный ввод/вывод файлов для POSIX и Windows, чтобы я мог написать его? Я не хочу использовать boost, потому что хочу сохранить свою небольшую базу кода. – orgazoid

+0

MSDN для Windows, man-страницы для Linux и google тоже хороши. Я отредактировал свой ответ, чтобы описать, как он работает, и дать вам имена ключевых функций, которые вы хотите исследовать. –

2

Библиотека Boost.Asio имеет ограниченную реализацию асинхронных операций ввода-вывода файлов (только оболочка Windows для HANDLE), поэтому она не подходит для вас. См. Также this вопрос.

Вы можете легко реализовать собственное асинхронное чтение, используя стандартные потоки и библиотеку Boost.Thread (или поддержку потоков, поддерживаемых платформой).

+0

Это многопоточность, а не асинхронный ввод-вывод, он оставляет программиста ответственным за синхронизацию доступа по потокам, а отмена запросов - настоящая боль. Вместо этого используйте настоящие асинхронные чтения. –

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