Skip to main content

Operador: __COMPARE_AND_SWAP

El operador multinúcleo es una extensión del estándar IEC 61131-3.

El operador se puede utilizar para implementar un semáforo, por ejemplo, para garantizar el acceso exclusivo a una variable que está siendo escrita por diferentes tareas.

__COMPARE_AND_SWAP obtiene un puntero a una variable del tipo de datos como entrada __XWORD, un valor antiguo y un valor nuevo, por ejemplo bMutex := __COMPARE_AND_SWAP(ADR(dwSynch), dwOld, dwNew);. El valor antiguo y el nuevo también pueden ser variables de tipo de datos __XWORD ser. el referenciado __XWORD-Se compara la variable con el valor anterior y si ambas son iguales se escribe el nuevo valor. El resultado de la función es TRUE, si se pudiera escribir el nuevo valor.

Sugerencia

el tipo de datos __XWORD se lleva a cabo automáticamente por el compilador en sistemas de 32 bits DWORD y en sistemas de 64 bits LWORD sustituido.

Esta operación es atómica, por lo que no puede ser interrumpida por otra tarea, incluso en plataformas multinúcleo.

ejemplo 155. Ejemplo

El siguiente ejemplo muestra un uso típico. Debe haber acceso exclusivo a una variable de tipo STRING implementado a través del puntero pstrOutput está dirigido.

Acceder a una cadena no es atómico. Si varias tareas escriben en la misma cadena al mismo tiempo, el contenido puede ser inconsistente.

Con esta función ahora es posible 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