Offload functions to worker threads with shared memory primitives for Node.js.
8
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: AtomicBool backed by Uint8Array

Devin Ivy 01304a7a 0d415a7c

+136
+1
src/index.ts
··· 3 3 export { workerPool } from './worker-pool.ts'; 4 4 export type { Runner } from './runner.ts'; 5 5 export { 6 + AtomicBool, 6 7 AtomicInt8, 7 8 AtomicUint8, 8 9 AtomicInt16,
+38
src/sync/atomic-bool.ts
··· 1 + export class AtomicBool { 2 + static readonly byteSize = 1; 3 + private readonly view: Uint8Array; 4 + 5 + constructor(buffer?: SharedArrayBuffer, byteOffset?: number) { 6 + const buf = buffer ?? new SharedArrayBuffer(1); 7 + const offset = byteOffset ?? 0; 8 + this.view = new Uint8Array(buf, offset, 1); 9 + } 10 + 11 + load(): boolean { 12 + return Atomics.load(this.view, 0) !== 0; 13 + } 14 + 15 + store(value: boolean): void { 16 + Atomics.store(this.view, 0, value ? 1 : 0); 17 + } 18 + 19 + and(value: boolean): boolean { 20 + return Atomics.and(this.view, 0, value ? 1 : 0) !== 0; 21 + } 22 + 23 + or(value: boolean): boolean { 24 + return Atomics.or(this.view, 0, value ? 1 : 0) !== 0; 25 + } 26 + 27 + xor(value: boolean): boolean { 28 + return Atomics.xor(this.view, 0, value ? 1 : 0) !== 0; 29 + } 30 + 31 + exchange(value: boolean): boolean { 32 + return Atomics.exchange(this.view, 0, value ? 1 : 0) !== 0; 33 + } 34 + 35 + compareExchange(expected: boolean, replacement: boolean): boolean { 36 + return Atomics.compareExchange(this.view, 0, expected ? 1 : 0, replacement ? 1 : 0) !== 0; 37 + } 38 + }
+1
src/sync/index.ts
··· 1 + export { AtomicBool } from './atomic-bool.ts'; 1 2 export { AtomicInt8 } from './atomic-int8.ts'; 2 3 export { AtomicUint8 } from './atomic-uint8.ts'; 3 4 export { AtomicInt16 } from './atomic-int16.ts';
+96
test/sync/atomic-bool.test.ts
··· 1 + import { describe, it } from 'node:test'; 2 + import assert from 'node:assert/strict'; 3 + import { AtomicBool } from 'moroutine'; 4 + 5 + describe('AtomicBool', () => { 6 + it('self-allocates and initializes to false', () => { 7 + const a = new AtomicBool(); 8 + assert.equal(a.load(), false); 9 + }); 10 + 11 + it('stores and loads true', () => { 12 + const a = new AtomicBool(); 13 + a.store(true); 14 + assert.equal(a.load(), true); 15 + }); 16 + 17 + it('stores and loads false', () => { 18 + const a = new AtomicBool(); 19 + a.store(true); 20 + a.store(false); 21 + assert.equal(a.load(), false); 22 + }); 23 + 24 + it('accepts an external buffer and byteOffset', () => { 25 + const buffer = new SharedArrayBuffer(4); 26 + const a = new AtomicBool(buffer, 2); 27 + a.store(true); 28 + assert.equal(new Uint8Array(buffer)[2], 1); 29 + }); 30 + 31 + it('exposes static byteSize of 1', () => { 32 + assert.equal(AtomicBool.byteSize, 1); 33 + }); 34 + 35 + it('and(false) clears, returns previous', () => { 36 + const a = new AtomicBool(); 37 + a.store(true); 38 + assert.equal(a.and(false), true); 39 + assert.equal(a.load(), false); 40 + }); 41 + 42 + it('and(true) preserves, returns previous', () => { 43 + const a = new AtomicBool(); 44 + a.store(true); 45 + assert.equal(a.and(true), true); 46 + assert.equal(a.load(), true); 47 + }); 48 + 49 + it('or(true) sets, returns previous', () => { 50 + const a = new AtomicBool(); 51 + assert.equal(a.or(true), false); 52 + assert.equal(a.load(), true); 53 + }); 54 + 55 + it('or(false) preserves, returns previous', () => { 56 + const a = new AtomicBool(); 57 + a.store(true); 58 + assert.equal(a.or(false), true); 59 + assert.equal(a.load(), true); 60 + }); 61 + 62 + it('xor(true) toggles, returns previous', () => { 63 + const a = new AtomicBool(); 64 + a.store(true); 65 + assert.equal(a.xor(true), true); 66 + assert.equal(a.load(), false); 67 + }); 68 + 69 + it('xor(false) preserves, returns previous', () => { 70 + const a = new AtomicBool(); 71 + a.store(true); 72 + assert.equal(a.xor(false), true); 73 + assert.equal(a.load(), true); 74 + }); 75 + 76 + it('exchange returns previous value', () => { 77 + const a = new AtomicBool(); 78 + a.store(true); 79 + assert.equal(a.exchange(false), true); 80 + assert.equal(a.load(), false); 81 + }); 82 + 83 + it('compareExchange succeeds when expected matches', () => { 84 + const a = new AtomicBool(); 85 + a.store(true); 86 + assert.equal(a.compareExchange(true, false), true); 87 + assert.equal(a.load(), false); 88 + }); 89 + 90 + it('compareExchange fails when expected does not match', () => { 91 + const a = new AtomicBool(); 92 + a.store(true); 93 + assert.equal(a.compareExchange(false, false), true); 94 + assert.equal(a.load(), true); 95 + }); 96 + });