Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to perform Cross-Platform Asynchronous File I/O in C++

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.

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.

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++.

EDIT: Don't want to use the Boost library because I want to keep a small code base.

like image 373
orgazoid Avatar asked Mar 10 '10 14:03

orgazoid


2 Answers

boost has an asio library, which I've not used before (it's not on NASA's list of approved third-party libraries).

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.

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.

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.

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.

like image 56
Ben Voigt Avatar answered Oct 01 '22 18:10

Ben Voigt


Boost.Asio library has limited implementation of asynchronous file I/O operations (only Windows wrapper for HANDLE) therefore it not suitable for you. See this question also.

You could easily implement your own asynchronous reading using standard streams and Boost.Thread library (or platform specific threads support).

like image 40
Kirill V. Lyadvinsky Avatar answered Oct 01 '22 19:10

Kirill V. Lyadvinsky