2010-03-04 15 views
10

En mi intento de desarrollar una clase de plantilla de puntero débil C++ segura para subprocesos, necesito verificar un indicador que indique que el objeto aún está activo; si es así, incremente el recuento de referencias del objeto y tengo que hacer los dos pasos de manera atómica.¿Cómo comparar e incrementar atómicamente?

Conozco la existencia de funciones intrínsecas proporcionadas por el compilador, por ejemplo _InterlockedCompareExchange() y _InterlockedIncrement(). Pero lo que quiero es una función interlockedCompareIncrement(), ¿hay alguna manera eficiente de simular esta intrínseca usando otras primitivas, al menos en la plataforma Windows x86?

+0

Si esto es en Windows, debe decirlo. – Gabe

Respuesta

7

Supongamos que value es la variable de su indicador. Debe declararse volatile.

long curvalue; 
long newvalue; 

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

Como se puede ver se puede generalizar esto a cualquier clase de aritmética que necesita cambiando las operaciones que se aplican para calcular newvalue.

Si desea comparar dos valores al mismo tiempo, su mejor opción es empacar ambos valores en una sola variable y luego operar en esa única variable. Dado que está utilizando una bandera combinada con un recuento de referencia, le recomendaría usar el bit más bajo de value como indicador "vivo", y luego incrementar/disminuir de 2 en 2. Esto le permite codificar tanto el indicador como el recuento de referencia en una sola variable de 32 bits.

+0

Parece que es lo que estoy buscando, lo voy a buscar más profundamente. –

+0

+1: Estaba buscando una función IncIfNot atómica. ¡Esto también es posible escribir con un bucle e _InterlockedCompareExchange()! – mmmmmmmm

1

Si desea que su biblioteca se ejecute en la CPU múltiple o varias máquinas básicas que tienen que usar el soporte de hardware proporcionado por la CPU. Aquí están algunas referencias para usted:

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

O usted tiene que utilizar el mecanismo proporcionado por el sistema operativo de bloqueo. Tal como

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

Cuestiones relacionadas