2009-07-05 11 views
11

Ho trovato diverse implementazioni per singolo produttore-singolo consumatore, ma nessuna per più produttori-singolo consumatore.Esiste una coda senza blocco "produttori multipli - consumatore singolo" per Delphi?

Esiste una coda senza blocco per "produttori multipli-unico consumatore" per Delphi?

+1

Una risposta molto interessante per quanto riguarda la regolazione delle prestazioni utilizzando algoritmi e alternative bloccabili: http://stackoverflow.com/questions/853316/is-critical-section-always-faster/853510#853510. – mghie

risposta

5

Coda di blocco da OmniThreadLibrary supporta più produttori. Puoi usarlo separatamente dalla libreria di threading (ad esempio puoi utilizzare l'unità OtlContainers in qualsiasi altro framework).

Come indicato da Daniele in basso, ci sono due code nella OmniThreadLibrary. Quello in OtlContainers supporta più produttori e più utenti mentre la versione "più intelligente" di OtlComm (che è solo un wrapper per la versione più semplice) è solo un singolo produttore/singolo consumatore.

documentazione è ancora un grosso problema del progetto OmniThreadLibrary :(. Alcune informazioni sulla coda può essere trovato here.

+0

Davvero? Ho usato la tua lista ma nel codice sorgente è un commento "triste" per me ... "{{: Blocco scrittore singolo, blocco lettore singolo senza blocco. } IOmniQueue = interfaccia [ '{AE6454A2-CDB4-43EE-9F1B-5A7307593EE9}']" voi dicono che è OmniQueue produttori MULTI, consumatore singolo abilitata? –

+0

Siamo spiacenti, il mio errore. "Di alto livello" coda OtlComm è singolo produttore/singolo consumatore. La coda "di basso livello" in OtlContainers è costituita da più produttori/più utenti, quindi è necessario utilizzare la variante più semplice dell'oggetto coda se si desidera utilizzare più produttori Ho corretto il testo sopra per fare riferimento al nome dell'unità corretto. – gabr

3

Potrebbe essere utile: Interlocked SList functions.

+0

+1. Si noti che un'alternativa a questo deve essere implementata se le applicazioni devono lavorare su sistemi Windows pre-XP. Si noti inoltre che non esiste un modo semplice per far bloccare il consumatore su una coda vuota. – mghie

+0

Le funzioni SList generano uno stack, non una coda. –

+2

@Rob Kennedy: Non completamente vero, se il consumatore utilizza InterlockedFlushSList() anziché InterlockedPopEntrySList() è libero di elaborare gli elementi dell'elenco in entrambe le direzioni. – mghie

2

http://svn.berlios.de/svnroot/repos/dzchart/utilities/dzLib/trunk/lockfree/

@Daniele Teti:

Il lettore deve attendere che tutti gli scrittori che hanno ancora accesso al centro della coda per uscire dal metodo di Enqueue. Poiché la prima cosa che il lettore fa nel metodo Dequeue sta fornendo una nuova coda per i nuovi scrittori che entrano in Enqueue, non dovrebbe volerci molto tempo per tutti gli scrittori che hanno un riferimento alla vecchia coda per uscire da Enqueue. Ma hai ragione: è privo di blocco solo per gli scrittori, ma potrebbe comunque richiedere che il thread del lettore attenda che alcuni scrittori escano da Enqueue.

+1

Sto recuperando questa lista ma ... i commenti del codice sono strani per un elenco "LockFree": "// Sfortunatamente è possibile che altri thread mantengano ancora un riferimento // alla vecchia coda. // Per essere sicuri al 100%, è necessario attendere fino al conteggio degli ActiveWriter // scende a 0 // Se al momento ci sono autori, attendiamo l'evento // che verrà impostato dal primo writer che diminuisce // ActiveWriters su 0. Se non ci sono, non c'è bisogno di aspettare. " Questo sembra un tipo di" attesa "sincronizzazione ... Mi sono sbagliato? (Mi sono trovato questi commenti all'interno della funzione TMultiWriteSingleReadLockFreeQueue.Dequeue) –

2

per una coda multiple-produttore/single-consumer/FIFO, si può facilmente fare uno LockFree usando SLIST o un banale stack LIFO Lock. Quello che fai è avere un secondo stack "privato" per il consumatore (che può essere fatto anche come SLIST per semplicità o qualsiasi altro modello di stack che scegli). stack privato Ogni volta che il LIFO privato viene espulso, esegui una risciacquo piuttosto che scendi dallo SLIST concorrente condiviso (afferrando l'intera catena SLIST) e poi fai scorrere l'elenco Flush in ordine spingendo gli oggetti nello stack privato

Funziona per singolo produttore/consumatore singolo e per produttore multiplo/consumatore singolo.

Tuttavia, non funziona per i casi di più produttori/consumatori multipli.

Problemi correlati