Files

43 lines
1.3 KiB
JavaScript

// Single-writer/single-reader latest-sample mailbox. Header: state, UTF-8 byte length.
// State 0 = empty, 1 = owned by a reader/writer, 2 = complete sample.
// Neither side waits: an unread sample can be replaced, and a busy publication is skipped.
export class SharedProfile {
constructor(buffer = new SharedArrayBuffer(1024 * 1024)) {
this.buffer = buffer;
this.header = new Int32Array(buffer, 0, 2);
this.bytes = new Uint8Array(buffer, 8);
this.encoder = new TextEncoder();
this.decoder = new TextDecoder();
}
write(json) {
const bytes = this.encoder.encode(json);
if (bytes.length > this.bytes.length) return false;
const state = Atomics.load(this.header, 0);
if (
state === 1 ||
Atomics.compareExchange(this.header, 0, state, 1) !== state
)
return false;
this.bytes.set(bytes);
this.header[1] = bytes.length;
Atomics.store(this.header, 0, 2);
return true;
}
read() {
if (Atomics.compareExchange(this.header, 0, 2, 1) !== 2) return;
let bytes;
try {
bytes = this.bytes.slice(0, this.header[1]);
} finally {
Atomics.store(this.header, 0, 0);
}
return JSON.parse(this.decoder.decode(bytes));
}
clear() {
Atomics.compareExchange(this.header, 0, 2, 0);
}
}