Start · Sprachen · JavaScript · Referenz · Atomics.xor()

Atomics.xor()

Methode

Führt atomar ein bitweises XOR mit <code>value</code> an Position <code>index</code> eines Integer-TypedArrays aus und gibt den alten Wert zurück.

seit JavaScript ES2017 Kategorie: method-property

Signatur

Atomics.xor(typedArray, index, value)

Beschreibung

Atomics.xor() liest den Wert an typedArray[index], verknüpft ihn bitweise per XOR (^) mit value, schreibt das Ergebnis zurück und liefert den ursprünglichen Wert. Die drei Schritte laufen als eine unteilbare Operation ab: Kein anderer Thread (z. B. ein Web Worker) kann zwischen Lesen und Schreiben auf die Speicherstelle zugreifen.

Typische Einsatzfälle sind das Umschalten (Toggeln) von Bit-Flags in einem SharedArrayBuffer, den mehrere Worker gemeinsam nutzen, etwa Status- oder Paritätsbits. Ein normales arr[i] ^= mask wäre hier eine Race Condition, weil Lesen und Schreiben getrennt stattfinden.

Die Methode funktioniert mit allen Integer-TypedArrays (Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, BigInt64Array, BigUint64Array), und zwar mit geteiltem wie mit nicht geteiltem Speicher. Bei den BigInt-Varianten muss value ein BigInt sein.

Parameter

Name Typ Default Beschreibung
$typedArray Pflicht Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|BigInt64Array|BigUint64Array Integer-TypedArray, meist über einem SharedArrayBuffer.
$index Pflicht number Position im typedArray, an der das XOR ausgeführt wird.
$value Pflicht number|bigint Operand für das XOR. Wird in den Elementtyp des Arrays umgewandelt (bei BigInt-Arrays: BigInt).

Rückgabewert

Typ
number|bigint
Beschreibung
Der alte Wert an typedArray[index] vor dem XOR. Den neuen Wert erhält man mit alt ^ value oder Atomics.load().

Beispiele

Grundlegende Verwendung

const sab = new SharedArrayBuffer(16);
const ta = new Uint8Array(sab);
ta[0] = 5; // 0b0101

const alt = Atomics.xor(ta, 0, 1); // 0b0101 ^ 0b0001
console.log(alt);
console.log(Atomics.load(ta, 0));
5 4

Status-Flag zwischen Worker und Hauptthread umschalten

// main.js
const FLAG_PAUSED = 0b0001;
const FLAG_DEBUG  = 0b0100;

const sab = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT);
const flags = new Int32Array(sab);

const worker = new Worker('worker.js');
worker.postMessage(flags);

// Pause-Flag atomar toggeln
const toggleFlag = (mask) => {
  const vorher = Atomics.xor(flags, 0, mask);
  const jetztGesetzt = ((vorher ^ mask) & mask) !== 0;
  console.log(`Flag ${mask}: ${jetztGesetzt ? 'an' : 'aus'}`);
};

toggleFlag(FLAG_PAUSED);
toggleFlag(FLAG_DEBUG);
toggleFlag(FLAG_PAUSED);
Flag 1: an Flag 4: an Flag 1: aus

Mit BigInt64Array

const big = new BigInt64Array(new SharedArrayBuffer(8));
big[0] = 0xFFn;

const alt = Atomics.xor(big, 0, 0x0Fn);
console.log(alt, big[0]);
255n 240n

// Wichtig · Fallstricke

  • Rückgabewert ist der alte Wert, nicht das Ergebnis. Das ist ein häufiger Denkfehler.
  • Wirft TypeError, wenn typedArray kein Integer-TypedArray ist (z. B. Float64Array oder Uint8ClampedArray), und RangeError, wenn index außerhalb der Grenzen liegt.
  • Bei BigInt64Array/BigUint64Array führt eine normale Zahl als value zu einem TypeError. Umgekehrt gilt das Gleiche.
  • Werte außerhalb des Elementbereichs werden abgeschnitten (z. B. bei Uint8Array modulo 256).
  • SharedArrayBuffer steht im Browser nur in cross-origin-isolierten Kontexten zur Verfügung. Dafür braucht es die Header Cross-Origin-Opener-Policy: same-origin und Cross-Origin-Embedder-Policy: require-corp (Grund: Schutz vor Spectre). Atomics selbst wird von allen modernen Browsern und von Node.js unterstützt.
  • Atomics.xor() weckt keine wartenden Threads. Dafür ist nach dem Schreiben Atomics.notify() nötig.