2010-03-10 11 views
11

Sto scrivendo un'applicazione che richiede l'uso di campioni audio di grandi dimensioni, in genere di circa 50 MB di dimensione. Un file contiene circa 80 singole registrazioni audio brevi, che possono essere riprodotte dalla mia applicazione in qualsiasi momento. Per questo motivo tutti i dati audio vengono caricati in memoria per un rapido accesso.Come eseguire l'I/O su file asincrono multipiattaforma in C++

Tuttavia, quando si carica uno di questi file, possono essere necessari molti secondi per la memoria perché ho bisogno di leggere una grande quantità di dati con ifstream, ovvero la mia GUI del programma è temporaneamente bloccata. Ho provato a mappare la memoria del mio file, ma questo causa enormi picchi di CPU e un pasticcio di audio ogni volta che ho bisogno di passare a un'area diversa del file, il che non è accettabile.

Quindi questo mi ha portato a pensare che l'esecuzione di un file asincrono leggendo risolverà il mio problema, cioè i dati vengono letti in un processo diverso e richiamano una funzione al completamento. Questo deve essere compatibile sia per Mac OS X che per Windows e in C++.

MODIFICA: Non voglio usare la libreria Boost perché voglio mantenere una piccola base di codice.

+0

re: Boost.asio, esiste anche come versione standalone, vedere http://think-async.com/ – Hasturkun

+0

Puoi anche leggere i tuoi dati in blocchi più piccoli che non richiederebbero tanto tempo, quindi lasciare che il ciclo di eventi in esecuzione tra. – kashiraja

risposta

8

boost ha una libreria asio, che non ho mai usato prima (non è nell'elenco delle librerie di terze parti approvate dalla NASA).

Il mio approccio è stato quello di scrivere il codice di lettura del file due volte, una volta per Windows, una volta per l'API POSIX aio, e quindi scegliere quello giusto con cui collegarsi.

Per Windows, utilizzare OVERLAPPED (è necessario abilitarlo nella chiamata CreateFile, quindi passare una struttura OVERLAPPED quando si legge). È possibile impostarlo su completamento (ReadFile) o chiamare un callback di completamento (ReadFileEx). Probabilmente dovrai modificare il tuo ciclo degli eventi principale per utilizzare MsgWaitForMultipleObjectsEx in modo da poter attendere gli eventi I/O o consentire l'esecuzione di callback, oltre a ricevere i messaggi della finestra WM_. MSDN ha documentazione per queste funzioni.

Per Linux, sono disponibili fadvise ed epoll, che utilizzeranno la cache readahead o aio_read che consentirà effettivamente le richieste di lettura asincrone. Riceverai un segnale al completamento della richiesta, che dovresti utilizzare per pubblicare un messaggio XWindows e attivare il ciclo di elaborazione degli eventi.

Entrambi sono leggermente diversi nei dettagli, ma l'effetto netto è lo stesso: si richiede una lettura che si completa in background, quindi il ciclo di invio dell'evento viene riattivato al termine dell'I/O.

+0

Sì, ho dovuto scrivere un paio di cose due volte prima, una per Windows uno per POSIX, quindi questo non sarebbe un problema. Dove posso andare a leggere i file I/O asincroni per POSIX e Windows in modo che io possa scriverlo? Non voglio usare boost perché voglio mantenere la mia piccola base di codice. – orgazoid

+0

MSDN per Windows, pagine man per Linux e google è ottimo. Ho modificato la mia risposta per delineare come funziona e darvi i nomi delle funzioni chiave che vorrete ricercare. –

2

Boost.Asio library ha un'implementazione limitata delle operazioni di I/O file asincrone (solo wrapper Windows per HANDLE) pertanto non è adatto a voi. Vedi anche la domanda this.

È possibile implementare facilmente la propria lettura asincrona utilizzando flussi standard e la libreria Boost.Thread (o supporto di thread specifici della piattaforma).

+0

Questo è multi-threading, non I/O asincrono, lascia al programmatore responsabile la sincronizzazione dell'accesso ai thread e l'annullamento delle richieste è un vero problema. Utilizzare invece letture asincrone reali. –

Problemi correlati