Operatore: __XADD
L'operatore multicore è un'estensione della norma IEC 61131-3.
L'operatore può essere utilizzato per implementare un contatore atomico. Se una variabile intera viene incrementata mediante addizione ordinaria, ad esempio iTest := iTest + 1;
, quindi questa operazione non viene eseguita atomicamente. Un altro accesso alla variabile potrebbe avvenire tra la lettura e la scrittura della variabile.
Se il contatore viene incrementato in più attività, il risultato del contatore può essere inferiore al numero di cicli di conteggio. Quindi, se due attività eseguono il codice sopra una volta e la variabile aveva precedentemente il valore 0
, la variabile può quindi avere il valore 1
. Ciò è particolarmente problematico se gli array vengono elaborati in più attività ed è richiesto un indice univoco per l'array in ogni ciclo di elaborazione.
Quando il __XADD
viene chiamato, ottiene un puntatore a un tipo DINT
variabile come primo ammonimento e un tipo DINT
valore come seconda somma. __XADD
restituisce il vecchio valore della prima somma e nello stesso passaggio aggiunge la seconda somma alla prima somma.
Ad esempio, la chiamata di funzione può essere simile a questa: diOld := __XADD(ADR(diVar), deAdd);
L'esempio seguente mostra un utilizzo tipico. Un array dovrebbe essere popolato da due attività. Nel processo, tutte le posizioni nell'array devono essere utilizzate e nessuna posizione deve essere sovrascritta.
Con questa funzione, più attività possono popolare un array booleano.
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