如何在C ++中执行跨平台异步文件I / O.

时间:2010-03-10 14:26:28

标签: c++ file asynchronous cross-platform io

我正在编写的应用程序需要使用大型音频多样本,通常大小约为50 MB。一个文件包含大约80个单独的短录音,可以随时由我的应用程序播放。因此,所有音频数据都会加载到内存中以便快速访问。

但是,当加载其中一个文件时,可能需要很长时间才能放入内存,因为我需要使用ifstream读取大量数据,这意味着我的程序GUI暂时被冻结。我已经尝试了内存映射我的文件,但每次我需要跳转到文件的不同区域时,这会导致巨大的CPU峰值和混乱的音频,这是不可接受的。

因此,这让我认为执行异步文件读取将解决我的问题,即在不同的进程中读取数据并在完成时调用函数。这需要兼容Mac OS X和Windows以及C ++。

编辑:不想使用Boost库,因为我想保留一个小的代码库。

2 个答案:

答案 0 :(得分:10)

boost有一个asio库,我之前没有使用它(它不在NASA的已批准的第三方库列表中)。

我自己的方法是编写两次文件读取代码,一次用于Windows,一次用于POSIX aio API,然后选择正确的链接。

对于Windows,使用OVERLAPPED(您必须在CreateFile调用中启用它,然后在阅读时传递OVERLAPPED结构)。您可以让它在完成时设置事件(ReadFile)或调用完成回调(ReadFileEx)。您可能需要更改主事件循环以使用MsgWaitForMultipleObjectsEx,这样您除了接收WM_窗口消息外,还可以等待I / O事件或允许回调运行。 MSDN有这些功能的文档。

对于Linux,有fadvise和epoll,它们将使用readahead缓存,或aio_read,它将允许实际的异步读取请求。当请求完成时,您将收到一个信号,您应该使用该信号发布XWindows消息并唤醒事件处理循环。

两者在细节上略有不同,但净效果是相同的 - 您请求在后台完成的读取,然后在I / O完成时唤醒事件调度循环。

答案 1 :(得分:2)

Boost.Asio库限制了异步文件I / O操作的实现(只有HANDLE的Windows包装器)因此它不适合您。另请参阅this问题。

您可以使用标准流和Boost.Thread库(或特定于平台的线程支持)轻松实现自己的异步读取。