Skip to main content

Operatore: __COMPARE_AND_SWAP

L'operatore multicore è un'estensione della norma IEC 61131-3.

L'operatore può essere utilizzato per implementare un semaforo, ad esempio per garantire l'accesso esclusivo a una variabile scritta da diversi task.

__COMPARE_AND_SWAP ottiene un puntatore a un tipo di dati __XWORD variabile, un vecchio valore e un nuovo valore come input (esempio: bMutex := __COMPARE_AND_SWAP(ADR(dwSynch), dwOld, dwNew);). I vecchi e i nuovi valori possono anche essere tipo di dati __XWORD variabili. Il referenziato __XWORD la variabile viene confrontata con il vecchio valore e se entrambi sono uguali, viene scritto il nuovo valore. Il risultato della funzione è TRUE quando è possibile scrivere il nuovo valore.

Suggerimento

Il compilatore sostituisce automaticamente il tipo di dati __XWORD con DWORD su sistemi a 32 bit e LWORD su sistemi a 64 bit.

Questa operazione è atomica, quindi non può essere interrotta da un'altra attività, anche su piattaforme multicore.

Esempio 155. Esempio

L'esempio seguente mostra un utilizzo tipico. Accesso esclusivo a un tipo STRING variabile, che viene indirizzata tramite il pstrOutput puntatore, dovrebbe essere implementato.

L'accesso a una stringa non è atomico. Se più attività scrivono contemporaneamente sulla stessa stringa, il contenuto potrebbe essere incoerente.

Con questa funzione è ora possibile scrivere la stessa variabile STRING in task diversi.

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