Как выполнить кросс-платформенный асинхронный ввод-вывод файлов в С++

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

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

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

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

Ответ 1

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

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

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

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

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

Ответ 2

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

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