2010-03-10 35 views
11

我正在编写一个应用程序需要使用大型音频多样本,通常大小约为50 MB。一个文件包含大约80个单独的短片录音,可以随时由我的应用程序播放。出于这个原因,所有的音频数据都被加载到内存中以便快速访问。如何在C++中执行跨平台异步文件I/O

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

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

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

+0

re:Boost.asio,它也作为独立版本存在,请参阅http://think-async.com/ – Hasturkun 2010-03-10 14:55:35

+0

您还可以以较小的块读取数据,这些块不会花费太多时间,然后让事件循环在两者之间运行。 – kashiraja 2011-05-18 17:22:58

回答

8

boost有一个asio库,我以前没有用过(它不在美国航天局的核准第三方库名单上)。

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

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

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

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

+0

是的,我必须在两次之前写两个事情,一个是用于POSIX的Windows,所以这不会成为问题。我在哪里可以阅读有关POSIX和Windows的异步文件I/O,以便我可以编写它?我不想使用boost,因为我想保留我的小代码库。 – orgazoid 2010-03-10 14:38:47

+0

适用于Windows的MSDN,适用于Linux的手册页和Google也很棒。我编辑了我的答案,概述了它的工作原理,并给出了你想要研究的关键功能的名称。 – 2010-03-10 14:56:57

2

Boost.Asio库对异步文件I/O操作的实现有限(只对HANDLE的Windows包装),因此它不适合你。也见this问题。

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

+0

这是多线程,而不是异步I/O,它让程序员负责跨线程同步访问,取消请求是一件非常痛苦的事情。改用真正的异步读取。 – 2010-03-10 19:30:27