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);
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