2011-03-16 15 views
6

Non ho molta esperienza con il multithreading e sto scrivendo un programma c che ritengo sia adatto all'esecuzione in due thread. Il programma ascolterà sulla porta seriale per i dati, leggerà ed elaborerà nuovi dati quando saranno disponibili, e pubblicherà i nuovi dati elaborati su altri moduli (irrilevanti) tramite una terza parte IPC api (è chiamata IPC con confusione) quando richiesto.Aiuto progettazione programma multithreaded

Per ricevere la richiesta di pubblicazione dei dati tramite IPC, il programma deve chiamare IPC_listenwait (wait_time) ;. Quindi se viene ricevuta una richiesta di pubblicazione mentre "listenwaiting" viene richiamato un gestore per pubblicare i dati più recenti.

Una possibilità è quella di farlo in un thread simile:

for(;;) { 
    read_serial(inputBuffer); 
    process_data(inputBuffer, processedData); //Process and store 
    IPC_listenwait(wait_time); //If a request to publish is received during this, 
}       //then a handler will be invoked and the newest piece of   
          //processedData will be published to other modules 

publishRequestHandler() { //Invoked when a message is received during IPC_listenwait 
    IPC_publish(newest(processedData)); 
} 

E questo funziona, ma per l'applicazione, è importante che il programma è molto sensibile alla richiesta di pubblicare nuovi dati, e che il i dati pubblicati sono i più recenti disponibili. Questi obiettivi non sono soddisfatti da quanto sopra, poiché i dati potrebbero arrivare dopo l'avvio del processo di attesa in attesa e prima che venga ricevuta una richiesta di pubblicazione del messaggio. Oppure il processo potrebbe essere in lettura/in elaborazione quando è in arrivo una richiesta di pubblicazione del messaggio, ma non sarà in grado di fornire assistenza fino alla successiva chiamata IPC_listenwait.

L'unico disegno mi viene in mente è quello di avere un thread di leggere, che sarà solo fare qualcosa di simile:

readThread() { 
    for(;;) { //pseudocode 
     select(); 
     read(inputBuffer); 
     process(inputBuffer, processedData); 
    } 
} 

E hanno il thread principale solo ascoltando per i messaggi in arrivo:

mainThread() { 
    IPC_listenwait(forever); 
} 

publishRequestHandler() { //Invoked when a message is received during IPC_listenwait 
    IPC_publish(newest(processedData)); 
} 

È questo il design che useresti? In tal caso, dovrò usare un semaforo quando accedo o scrivo processedData?

Questo mi darà una buona reattività?

Grazie

risposta

4

Sei quasi sulla strada giusta.

L'unica cosa a cui bisogna fare attenzione è l'accesso simultaneo ai dati pubblicabili, perché non si vuole che un thread lo stia rovinando mentre un altro sta cercando di leggerlo. Per evitare ciò, utilizzare una coppia di buffer e un puntatore protetto da mutex a seconda di quale è considerato corrente. Quando process_data() ha qualcosa di pronto, dovrebbe scaricare i risultati nel buffer non corrente, bloccare il mutex del puntatore, reindirizzare il puntatore al buffer contenente i nuovi dati e quindi rilasciare il mutex. Allo stesso modo, il publisher dovrebbe bloccare il mutex del puntatore mentre legge i dati correnti, il che obbligherà tutto ciò che potrebbe voler nascondere. Questo è un po 'più complesso di un singolo buffer protetto da mutex, ma ti garantirà che hai sempre qualcosa da pubblicare mentre vengono preparati i nuovi dati.

Se la fase di elaborazione richiede abbastanza tempo da consentire la lettura di più serie di dati, è possibile suddividere il thread di lettura/elaborazione in due e consentire al lettore di assicurarsi che il processore ottenga sempre l'ultimo e il massimo finiremo per elaborare cose che non pubblicherete mai.

Eccellente prima domanda, a proposito. Avere un upvote

+0

Ahh, la soluzione dei due buffer è semplice ma geniale! Grazie –