演算子:__XADD
マルチコア演算子は、IEC61131-3規格の拡張です。
演算子は、アトミックカウンターを実装するために使用できます。整数変数が通常の加算によってインクリメントされる場合、たとえば iTest := iTest + 1;、この場合、この操作はアトミックに実行されません。変数への別のアクセスは、変数の読み取りと書き込みの間に行われる可能性があります。
カウンターが複数のタスクでインクリメントされる場合、カウンターの結果はカウントサイクルの数より少なくなる可能性があります。したがって、2つのタスクが上記のコードを一度に実行し、変数が以前に値を持っていた場合 0、その場合、変数は値を持つことができます 1。これは、配列が複数のタスクで処理されており、各処理サイクルで配列に一意のインデックスが必要な場合に特に問題になります。
いつ __XADD 演算子が呼び出され、型へのポインタを取得します DINT 最初の被加数および型としての変数 DINT 2番目の被加数としての値。 __XADD 最初の被加数の古い値を返し、同じステップで2番目の被加数を最初の被加数に追加します。
たとえば、関数呼び出しは次のようになります。 diOld := __XADD(ADR(diVar), deAdd);
例 157. 例
次の例は、一般的な使用法を示しています。配列は2つのタスクから移入する必要があります。このプロセスでは、配列内のすべての位置を使用する必要があり、位置を上書きしないでください。
この関数を使用すると、複数のタスクでブール配列を設定できます。
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