Skip to main content

Opérateur : __COMPARE_AND_SWAP

L'opérateur multicœur est une extension de la norme CEI 61131-3.

L'opérateur peut être utilisé pour implémenter un sémaphore, par exemple pour garantir un accès exclusif à une variable écrite par différentes tâches.

__COMPARE_AND_SWAP obtient un pointeur vers un type de données __XWORD variable, une ancienne valeur et une nouvelle valeur en entrée (exemple : bMutex := __COMPARE_AND_SWAP(ADR(dwSynch), dwOld, dwNew);). Les anciennes et nouvelles valeurs peuvent également être des types de données __XWORD variables. Le référencé __XWORD variable est comparée à l'ancienne valeur et si les deux sont égales, la nouvelle valeur est écrite. Le résultat de la fonction est TRUE lorsque la nouvelle valeur pourrait être écrite.

Astuce

Le compilateur remplace automatiquement le type de données __XWORD avec DWORD sur les systèmes 32 bits et LWORD sur les systèmes 64 bits.

Cette opération est atomique, elle ne peut donc pas être interrompue par une autre tâche, même sur des plateformes multicœurs.

Exemple 155. Exemple

L'exemple suivant montre une utilisation typique. Accès exclusif à un type STRING variable, qui est adressée via la pstrOutput pointeur, doit être implémenté.

L'accès à une chaîne n'est pas atomique. Si plusieurs tâches écrivent dans la même chaîne en même temps, le contenu peut être incohérent.

Avec cette fonction, il est maintenant possible d'écrire la même variable STRING dans différentes tâches.

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