How to perform Cross-Platform Asynchronous File I/O in C++(如何在 C++ 中执行跨平台异步文件 I/O)
问题描述
我正在编写一个需要使用大型音频多样本的应用程序,通常大小约为 50 mb.一个文件包含大约 80 个单独的短录音,我的应用程序可以随时播放这些录音.因此,所有音频数据都会加载到内存中以便快速访问.
I am writing an application needs to use large audio multi-samples, usually around 50 mb in size. One file contains approximately 80 individual short sound recordings, which can get played back by my application at any time. For this reason all the audio data gets loaded into memory for quick access.
但是,当加载其中一个文件时,将其放入内存可能需要几秒钟的时间,因为我需要使用 ifstream 读取大量数据,这意味着我的程序 GUI 会暂时冻结.我尝试过内存映射我的文件,但是每次我需要跳转到文件的不同区域时,这都会导致巨大的 CPU 峰值和混乱的音频,这是不可接受的.
However, when loading one of these files, it can take many seconds to put into memory because I need to read a large amount of data with ifstream, meaning my program GUI is temporarily frozen. I have tried memory mapping my file but this causes huge CPU spikes and a mess of audio every time I need to jump to a different area of the file, which is not acceptable.
所以这让我认为执行异步文件读取将解决我的问题,即数据在不同的进程中读取并在完成时调用函数.这需要同时兼容 Mac OS X 和 Windows 以及 C++.
So this has led me to think that performing an Asynchronous file read will solve my problem, that is the data gets read in a different process and calls a function on completion. This needs to be both compatible for Mac OS X and Windows and in C++.
不想使用 Boost 库,因为我想保留一个小的代码库.
Don't want to use the Boost library because I want to keep a small code base.
推荐答案
boost 有一个 asio 库,我以前没有使用过(它不在 NASA 批准的第三方库列表中).
boost has an asio library, which I've not used before (it's not on NASA's list of approved third-party libraries).
我自己的方法是编写两次文件读取代码,一次用于 Windows,一次用于 POSIX aio API,然后选择正确的链接.
My own approach has been to write the file reading code twice, once for Windows, once for the POSIX aio API, and then just pick the right one to link with.
对于 Windows,使用 OVERLAPPED(你必须在 CreateFile 调用中启用它,然后在你阅读时传递一个 OVERLAPPED 结构).您可以让它在完成时设置事件 (ReadFile) 或调用完成回调 (ReadFileEx).您可能需要更改主事件循环以使用 MsgWaitForMultipleObjectsEx,这样除了接收 WM_ 窗口消息之外,您还可以等待 I/O 事件或允许运行回调.MSDN 有这些功能的文档.
For Windows, use OVERLAPPED (you have to enable it in the CreateFile call, then pass an OVERLAPPED structure when you read). You can either have it set an event on completion (ReadFile) or call a completion callback (ReadFileEx). You'll probably need to change your main event loop to use MsgWaitForMultipleObjectsEx so you can either wait for the I/O events or allow callbacks to run, in addition to receiving WM_ window messages. MSDN has documentation for these functions.
对于 Linux,有 fadvise 和 epoll,它们将使用预读缓存,或者 aio_read,它将允许实际的异步读取请求.当请求完成时,您将收到一个信号,您应该使用它来发布 XWindows 消息并唤醒您的事件处理循环.
For Linux, there's either fadvise and epoll, which will use the readahead cache, or aio_read which will allow actual async read requests. You'll get a signal when the request completes, which you should use to post an XWindows message and wake up your event processing loop.
两者在细节上略有不同,但最终效果相同——您请求在后台完成的读取,然后在 I/O 完成时唤醒您的事件调度循环.
Both are a little different in the details, but the net effect is the same -- you request a read which completes in the background, then your event dispatch loop gets woken up when the I/O finishes.
这篇关于如何在 C++ 中执行跨平台异步文件 I/O的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何在 C++ 中执行跨平台异步文件 I/O
基础教程推荐
- 如何“在 Finder 中显示"或“在资源管理器中显 2021-01-01
- Windows Media Foundation 录制音频 2021-01-01
- 为 C/C++ 中的项目的 makefile 生成依赖项 2022-01-01
- 使用从字符串中提取的参数调用函数 2022-01-01
- 如何在不破坏 vtbl 的情况下做相当于 memset(this, ...) 的操作? 2022-01-01
- 从 std::cin 读取密码 2021-01-01
- 管理共享内存应该分配多少内存?(助推) 2022-12-07
- 如何使图像调整大小以在 Qt 中缩放? 2021-01-01
- 在 C++ 中循环遍历所有 Lua 全局变量 2021-01-01
- 为什么语句不能出现在命名空间范围内? 2021-01-01