views:

462

answers:

2

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++. Can anyone give me some help?

Thanks in advance :-)

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

+1  A: 

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

Kirill V. Lyadvinsky
That's multi-threading, not asynchronous I/O, it leaves the programmer responsible with synchronizing access across threads, and cancelling requests is a real pain. Use real async reads instead.
Ben Voigt
+2  A: 

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.

Ben Voigt
Yes, I've had to write a couple of things twice before, one for Windows one for POSIX, so this wouldn't be a problem. Where can I go to read up on Asynchronous file I/O for POSIX and Windows so I can write it? I don't want to use boost because I want to retain my small code base.
orgazoid
MSDN for Windows, man pages for Linux, and google is great too. I've edited my answer to outline how it works and give you the names of key functions you'll want to research.
Ben Voigt