Skip to main content

Opérateur : __XADD

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

L'opérateur peut être utilisé pour mettre en œuvre un compteur atomique. Si une variable entière est incrémentée au moyen d'une addition ordinaire, par exemple iTest := iTest + 1;, alors cette opération n'est pas exécutée de manière atomique. Un autre accès à la variable pourra avoir lieu entre la lecture et l'écriture de la variable.

Si le compteur est incrémenté dans plusieurs tâches, le résultat du compteur peut être inférieur au nombre de cycles de comptage. Donc, si deux tâches exécutent le code ci-dessus une fois et que la variable avait précédemment la valeur 0, alors la variable peut alors prendre la valeur 1. Cela est particulièrement problématique si les tableaux sont traités dans plusieurs tâches et qu'un index unique est requis pour le tableau dans chaque cycle de traitement.

Quand le __XADD l'opérateur est appelé, il obtient un pointeur vers un type DINT variable comme premier sommand et un type DINT valeur comme deuxième sommation. __XADD renvoie l'ancienne valeur de la première sommation et, dans la même étape, ajoute la deuxième sommation à la première sommation.

Par exemple, l'appel de fonction peut ressembler à ceci : diOld := __XADD(ADR(diVar), deAdd);

Exemple 156. Exemple

L'exemple suivant montre une utilisation typique. Un tableau doit être rempli à partir de deux tâches. Dans le processus, toutes les positions du tableau doivent être utilisées et aucune position ne doit être écrasée.

Avec cette fonction, plusieurs tâches peuvent remplir un tableau booléen.

FUNCTION WriteToNextArrayPosition : BOOL
VAR_EXTERNAL
        g_diIndex : DINT;  // Index and array are globally defined and used by multiple tasks
        g_boolArray : ARRAY [0..1000] OF BOOL;
END_VAR
VAR_INPUT
        bToWrite : BOOL;
END_VAR
VAR
        diIndex : DWORD;
END_VAR

diIndex := __XADD(ADR(g_diIndex), 1);       // Returns a unique index
WriteToNextArrayPosition := FALSE;
IF (diIndex >= 0 AND diIndex <= 1000) THEN
        g_boolArray[diIndex] := bToWrite;         //Writes to unique index
        WriteToNextArrayPosition := TRUE;         // TRUE: Array was not full yet
END_IF