2010-03-04 4 views
10

Nel mio tentativo di sviluppare una classe modello di puntatore debole C++ a prova di thread, ho bisogno di controllare un flag che indichi che l'oggetto è ancora vivo, in caso affermativo incrementare il conteggio dei riferimenti dell'oggetto e ho bisogno di eseguire entrambi i passaggi atomicamente.Come confrontare e incrementare atomicamente?

Conosco l'esistenza di funzioni intrinseche fornite dal compilatore, ad esempio _InterlockedCompareExchange() e _InterlockedIncrement(). Ma quello che voglio è una funzione interlockedCompareIncrement(), c'è un modo efficace per simulare questo intrinseco usando altre primitive, almeno sulla piattaforma Windows x86?

+0

Se questo è su Windows, si dovrebbe dire così. – Gabe

risposta

7

Supponiamo che value sia la variabile del flag. Dovrebbe essere dichiarato volatile.

long curvalue; 
long newvalue; 

do 
{ 
    curvalue = value; 
    newvalue = curvalue + 1; 
} 
while(_InterlockedCompareExchange(&value, newvalue, curvalue) != curvalue); 

Come si vede si può generalizzare questo a qualunque tipo di aritmetica è necessario modificando le operazioni che vengono applicate per calcolare newvalue.

Se si desidera confrontare due valori contemporaneamente, si consiglia di raggruppare entrambi i valori in una singola variabile e quindi operare su quella singola variabile. Poiché utilizzi un flag combinato con un conteggio dei riferimenti, ti consigliamo di utilizzare il bit più basso di value come indicatore "vivo" e quindi aumentare/diminuire di 2 alla volta. Ciò consente di codificare sia il flag che il conteggio dei riferimenti in una singola variabile a 32 bit.

+0

Sembra quello che sto cercando, lo guarderò più a fondo. –

+0

+1: cercavo una funzione IncIfNot atomica. È anche possibile scrivere con un loop e _InterlockedCompareExchange()! – mmmmmmmm

1

Se si desidera la vostra libreria di girare su più CPU o più macchine di base si deve utilizzare il supporto hardware fornito dalla CPU. Qui ci sono alcuni riferimenti per voi:

http://en.wikipedia.org/wiki/Test-and-set http://software.intel.com/en-us/forums/showthread.php?t=47498

o si deve usare meccanismo previsto dal sistema operativo di blocco. Come ad esempio

http://msdn.microsoft.com/en-us/library/ms684841%28VS.85%29.aspx o http://en.wikipedia.org/wiki/POSIX_Threads