__COMPARE_AND_SWAP

Descripción general

Este operador no se especifica en el estándar IEC 61131-3.

Puede usarse para implementar un semáforo, por ejemplo, para contribuir a garantizar el acceso exclusivo a una variable escrita por diferentes tareas.

Los siguientes elementos se asignan a __COMPARE_AND_SWAP:

  • Puntero a una variable de tipo de datos __XWORD

  • Valor anterior como entrada, también puede ser variable de tipo de datos __XWORD

  • Valor nuevo como entrada, también puede ser variable de tipo de datos __XWORD

Ejemplo: bMutex := __COMPARE_AND_SWAP(ADR(dwSynch), dwOld, dwNew);

La variable __XWORD referenciada se compara con el valor anterior. Si ambos son iguales, se escribe el nuevo valor. El resultado de la función es TRUE si se escribe el nuevo valor.

NOTA: El compilador sustituye el tipo de datos __XWORD por DWORD en sistemas de 32 bits y por LWORD en sistemas de 64 bits.

Esta operación atómica no la puede interrumpir otra tarea, ni siquiera en plataformas multicore.

Ejemplo

En el siguiente ejemplo se muestra un caso de uso típico: implementación de acceso exclusivo a una variable de tipo STRING que se direcciona con el puntero pstrOutput.

Como el acceso a una variable de tipo STRING no es atómico, el contenido puede ser incoherente si varias tareas escriben en la misma cadena al mismo tiempo.

Usar la función de operador __COMPARE_AND_SWAP le permite escribir la misma variable STRING en diferentes tareas.

FUNCTION ExclusiveStringWrite : BOOL
VAR_INPUT
    strToWrite : STRING;
    pstrOutput : POINTER TO STRING;
END_VAR
VAR_STAT
  dwSynch : __XWORD;
END_VAR
VAR
    bMutex: BOOL;
END_VAR

bMutex:= __COMPARE_AND_SWAP(ADR(dwSynch), 0, 1);
(* compare with 0 and write 1 as atomic operation *)
IF bMutex THEN                      // bMutex is TRUE if write could be done
    pstrOutput^ := strToWrite;     // Now you can write safely on the string
    dwSynch := 0;                  // The __XWORD variable must be reset.
    ExclusiveStringWrite := TRUE; // Writing was successful
ELSE
    ExclusiveStringWrite := FALSE; // Writing was not successful
END_IF