Как выполнить кросс-платформенный асинхронный файловый ввод / вывод в C ++ - PullRequest
12 голосов
/ 10 марта 2010

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

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

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

РЕДАКТИРОВАТЬ: не хочу использовать библиотеку Boost, потому что я хочу сохранить небольшую базу кода.

Ответы [ 2 ]

10 голосов
/ 10 марта 2010

boost имеет библиотеку asio, которой я раньше не пользовался (ее нет в списке утвержденных сторонних библиотек НАСА).

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

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

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

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

2 голосов
/ 10 марта 2010

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

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

...