2009-05-22 14 views
5

Ho bisogno di creare un sistema di lavoratori (rappresentati come thread) e (più) code. I singoli lavori sono in attesa in una delle code e attende che un thread di lavoro li elabori. Ogni lavoratore può elaborare i lavori solo da alcune code. No spin-waiting. C/C++, pthreads, POSIX standard.C++ - thread e code multiple

Il problema per me è la cosa delle "code multiple". So come implementarlo con una singola coda. I lavoratori devono attendere tutte le code che possono processare (aspettarne QUALSIASI).

In Windows vorrei utilizzare WaitForMultipleObjects, ma questo deve essere multipiattaforma.

Non voglio alcun codice particolare per questo, solo un suggerimento o una descrizione del modello che dovrei usare. Grazie in anticipo.

+0

È possibile utilizzare l'incremento? – PiNoYBoY82

risposta

4

Quello che puoi fare è usare un condition variable. I tuoi thread di lavoro devono attendere una variabile di condizione. Quando un lavoro viene aggiunto a una qualsiasi delle code di lavoro, segnalare la variabile di condizione. Quindi, quando il thread di lavoro si attiva, controlla le code in attesa. Se qualcuno di loro ha un lavoro, toglie quel lavoro dalla coda. Altrimenti, torna in attesa sulla variabile condition. In attesa di una variabile di condizione, il thread si interrompe, quindi non consuma il tempo della CPU.

Ovviamente, è ovvio che è necessario proteggere tutti gli accessi alle code di lavoro con un mutex (ad esempio pthread_mutex_t).

+0

Buona idea, ma questa operazione sveglierà tutti i thread di lavoro quando si aggiunge un lavoro a una coda vuota. Suppongo che lo farò in questo modo comunque, ma c'è un modo per riattivare solo il thread "corretto" (e idealmente solo uno di tutti i thread corretti)? –

+0

pthread_cond_signal() risveglierà "almeno un thread" in attesa sulla variabile condition, mentre pthread_cond_broadcast() farà scattare tutti i thread. In teoria, pthread_cond_signal() dovrebbe solo svegliare un thread la maggior parte delle volte, ma non so se questo è vero o no nella pratica. –

+0

Ma nella tua soluzione I * ho bisogno * di svegliare tutti i thread, perché un lavoro potrebbe essere in una coda che il lavoratore * uno * non elabora. –

1

Se non ci sono molti lavoratori per ogni coda, è possibile creare una variabile di condizione per ciascun lavoratore.

0

Quello che vorrei fare è utilizzare boost :: asio per mettere in coda i dati in modo che i tuoi thread multipli possano provarci. È possibile passare un riferimento alla coda tramite il comando post e avere il processo del thread di conseguenza.

0

Invece di avere un blocco separato per ogni coda, perché non avere un blocco per tutte le code?

  1. Attendere sulla serratura
  2. ottenere il blocco
  3. Dequeue da qualsiasi coda
  4. Rilasciare il blocco
  5. processo la voce accodamento
  6. Goto fase 1

Supponendo che il dequio richiede un tempo trascurabile (quindi il blocco viene sempre trattenuto solo per un tempo trascurabile) lì potrebbe non essere necessario più di un lucchetto.

+0

Non penso che funzionerà. Un lavoratore elabora solo i lavori da una coda specifica. Se c'è un solo lavoro in una coda "cattiva", il lavoratore sarà occupato-in attesa fino a quando un altro lavoratore non prenderà il lavoro. –

0

Si potrebbe fare qualcosa del genere: ogni lavoro ha una "coda" ad esso associata. Es:

Supponiamo di avere 2 code. Il tuo posto di lavoro potrebbe dire:

job[0].queue = 1; /* That job is in queue 1 */ 
job[1].queue = 1; 
job[2].queue = 2; /* this job is in queue 2 */ 
... 
etc 

Allora hai il tuo "sacco di fili". Una discussione prende semplicemente un lavoro - per esempio, lavoro [2]. Se quel thread è consentito solo per elaborare i lavori dalla coda 1, rimette il lavoro nella coda pronta e sceglie un lavoro diverso.

Quindi ogni thread sa quali code è consentito elaborare e quando sceglie un lavoro, si assicura che il campo "coda" del lavoro corrisponda. Se non lo fa, sceglie un altro lavoro.

(questo è per molti aspetti il ​​modo in cui la pianificazione dei processi funziona su linux su più core. Ogni processo ha una maschera di bit che indica a quali processori è consentito eseguire, e quindi il processore si assicura che sia "consentito" di eseguire quel processo prima di farlo)

5

ne dite di:.

  • tutti i thread di lavoro aspettare su un semaforo
  • quando nulla viene aggiunto alla coda, il semaforo viene incrementato, che risveglia un unico filo
  • la filo chec ks le code si è interessato, processi uno di loro e risale al attesa sul semaforo

Sarà necessario mutex supplementare (es) per il controllo effettivo leggere & scrive alle code.

+1

+1 Vado con Neil su questo :) – ralphtheninja

0

Ho pensato a questo di recente e l'unica idea che potrei ottenere è (supponendo che tu abbia code thread-safe) per avere sempre solo thread multipli che servono una singola coda.

È quindi possibile avere uno o più thread di produzione che aggiungono lavori a una singola coda e uno o più thread di lavoro bloccati sulla coda finché non trovano qualcosa da elaborare.

Se si hanno più code che più thread di lavoro devono eseguire il polling, è possibile che una soluzione aggiunga un thread aggiuntivo per ogni coda e una coda aggiuntiva. I thread aggiuntivi ogni blocco sulla loro singola coda, ma semplicemente inoltrano i lavori alla coda aggiuntiva. Ora il thread di lavoro esistente torna al blocco su una singola coda.