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.

refactor: rename AtomicX classes to XAtomic for naming consistency

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+115 -115
+2 -2
examples/atomics/increment.ts
··· 1 1 import { mo } from '../../src/index.ts'; 2 - import type { AtomicInt32 } from '../../src/index.ts'; 2 + import type { Int32Atomic } from '../../src/index.ts'; 3 3 4 - export const increment = mo(import.meta, (counter: AtomicInt32): number => { 4 + export const increment = mo(import.meta, (counter: Int32Atomic): number => { 5 5 return counter.add(1); 6 6 });
+9 -9
src/index.ts
··· 39 39 Int64, 40 40 Uint64, 41 41 Bool, 42 - AtomicInt8, 43 - AtomicUint8, 44 - AtomicInt16, 45 - AtomicUint16, 46 - AtomicInt32, 47 - AtomicUint32, 48 - AtomicInt64, 49 - AtomicUint64, 50 - AtomicBool, 42 + Int8Atomic, 43 + Uint8Atomic, 44 + Int16Atomic, 45 + Uint16Atomic, 46 + Int32Atomic, 47 + Uint32Atomic, 48 + Int64Atomic, 49 + Uint64Atomic, 50 + BoolAtomic, 51 51 Mutex, 52 52 MutexGuard, 53 53 RwLock,
+3 -3
src/shared/atomic-bool.ts src/shared/bool-atomic.ts
··· 1 1 import { registerSync } from './reconstruct.ts'; 2 2 3 - export class AtomicBool { 3 + export class BoolAtomic { 4 4 static readonly byteSize = 1; 5 5 static readonly byteAlignment = 1; 6 6 private readonly view: Uint8Array; ··· 40 40 } 41 41 42 42 [Symbol.for('moroutine.shared')](): { tag: string; buffer: SharedArrayBuffer; byteOffset: number } { 43 - return { tag: 'AtomicBool', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 43 + return { tag: 'BoolAtomic', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 44 44 } 45 45 } 46 46 47 - registerSync('AtomicBool', AtomicBool); 47 + registerSync('BoolAtomic', BoolAtomic);
+3 -3
src/shared/atomic-int16.ts src/shared/int16-atomic.ts
··· 1 1 import { registerSync } from './reconstruct.ts'; 2 2 3 - export class AtomicInt16 { 3 + export class Int16Atomic { 4 4 static readonly byteSize = 2; 5 5 static readonly byteAlignment = 2; 6 6 private readonly view: Int16Array; ··· 48 48 } 49 49 50 50 [Symbol.for('moroutine.shared')](): { tag: string; buffer: SharedArrayBuffer; byteOffset: number } { 51 - return { tag: 'AtomicInt16', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 51 + return { tag: 'Int16Atomic', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 52 52 } 53 53 } 54 54 55 - registerSync('AtomicInt16', AtomicInt16); 55 + registerSync('Int16Atomic', Int16Atomic);
+3 -3
src/shared/atomic-int32.ts src/shared/int32-atomic.ts
··· 1 1 import { registerSync } from './reconstruct.ts'; 2 2 3 - export class AtomicInt32 { 3 + export class Int32Atomic { 4 4 static readonly byteSize = 4; 5 5 static readonly byteAlignment = 4; 6 6 private readonly view: Int32Array; ··· 48 48 } 49 49 50 50 [Symbol.for('moroutine.shared')](): { tag: string; buffer: SharedArrayBuffer; byteOffset: number } { 51 - return { tag: 'AtomicInt32', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 51 + return { tag: 'Int32Atomic', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 52 52 } 53 53 } 54 54 55 - registerSync('AtomicInt32', AtomicInt32); 55 + registerSync('Int32Atomic', Int32Atomic);
+3 -3
src/shared/atomic-int64.ts src/shared/int64-atomic.ts
··· 1 1 import { registerSync } from './reconstruct.ts'; 2 2 3 - export class AtomicInt64 { 3 + export class Int64Atomic { 4 4 static readonly byteSize = 8; 5 5 static readonly byteAlignment = 8; 6 6 private readonly view: BigInt64Array; ··· 48 48 } 49 49 50 50 [Symbol.for('moroutine.shared')](): { tag: string; buffer: SharedArrayBuffer; byteOffset: number } { 51 - return { tag: 'AtomicInt64', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 51 + return { tag: 'Int64Atomic', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 52 52 } 53 53 } 54 54 55 - registerSync('AtomicInt64', AtomicInt64); 55 + registerSync('Int64Atomic', Int64Atomic);
+3 -3
src/shared/atomic-int8.ts src/shared/int8-atomic.ts
··· 1 1 import { registerSync } from './reconstruct.ts'; 2 2 3 - export class AtomicInt8 { 3 + export class Int8Atomic { 4 4 static readonly byteSize = 1; 5 5 static readonly byteAlignment = 1; 6 6 private readonly view: Int8Array; ··· 48 48 } 49 49 50 50 [Symbol.for('moroutine.shared')](): { tag: string; buffer: SharedArrayBuffer; byteOffset: number } { 51 - return { tag: 'AtomicInt8', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 51 + return { tag: 'Int8Atomic', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 52 52 } 53 53 } 54 54 55 - registerSync('AtomicInt8', AtomicInt8); 55 + registerSync('Int8Atomic', Int8Atomic);
+3 -3
src/shared/atomic-uint16.ts src/shared/uint16-atomic.ts
··· 1 1 import { registerSync } from './reconstruct.ts'; 2 2 3 - export class AtomicUint16 { 3 + export class Uint16Atomic { 4 4 static readonly byteSize = 2; 5 5 static readonly byteAlignment = 2; 6 6 private readonly view: Uint16Array; ··· 48 48 } 49 49 50 50 [Symbol.for('moroutine.shared')](): { tag: string; buffer: SharedArrayBuffer; byteOffset: number } { 51 - return { tag: 'AtomicUint16', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 51 + return { tag: 'Uint16Atomic', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 52 52 } 53 53 } 54 54 55 - registerSync('AtomicUint16', AtomicUint16); 55 + registerSync('Uint16Atomic', Uint16Atomic);
+3 -3
src/shared/atomic-uint32.ts src/shared/uint32-atomic.ts
··· 1 1 import { registerSync } from './reconstruct.ts'; 2 2 3 - export class AtomicUint32 { 3 + export class Uint32Atomic { 4 4 static readonly byteSize = 4; 5 5 static readonly byteAlignment = 4; 6 6 private readonly view: Uint32Array; ··· 48 48 } 49 49 50 50 [Symbol.for('moroutine.shared')](): { tag: string; buffer: SharedArrayBuffer; byteOffset: number } { 51 - return { tag: 'AtomicUint32', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 51 + return { tag: 'Uint32Atomic', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 52 52 } 53 53 } 54 54 55 - registerSync('AtomicUint32', AtomicUint32); 55 + registerSync('Uint32Atomic', Uint32Atomic);
+3 -3
src/shared/atomic-uint64.ts src/shared/uint64-atomic.ts
··· 1 1 import { registerSync } from './reconstruct.ts'; 2 2 3 - export class AtomicUint64 { 3 + export class Uint64Atomic { 4 4 static readonly byteSize = 8; 5 5 static readonly byteAlignment = 8; 6 6 private readonly view: BigUint64Array; ··· 48 48 } 49 49 50 50 [Symbol.for('moroutine.shared')](): { tag: string; buffer: SharedArrayBuffer; byteOffset: number } { 51 - return { tag: 'AtomicUint64', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 51 + return { tag: 'Uint64Atomic', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 52 52 } 53 53 } 54 54 55 - registerSync('AtomicUint64', AtomicUint64); 55 + registerSync('Uint64Atomic', Uint64Atomic);
+3 -3
src/shared/atomic-uint8.ts src/shared/uint8-atomic.ts
··· 1 1 import { registerSync } from './reconstruct.ts'; 2 2 3 - export class AtomicUint8 { 3 + export class Uint8Atomic { 4 4 static readonly byteSize = 1; 5 5 static readonly byteAlignment = 1; 6 6 private readonly view: Uint8Array; ··· 48 48 } 49 49 50 50 [Symbol.for('moroutine.shared')](): { tag: string; buffer: SharedArrayBuffer; byteOffset: number } { 51 - return { tag: 'AtomicUint8', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 51 + return { tag: 'Uint8Atomic', buffer: this.view.buffer as SharedArrayBuffer, byteOffset: this.view.byteOffset }; 52 52 } 53 53 } 54 54 55 - registerSync('AtomicUint8', AtomicUint8); 55 + registerSync('Uint8Atomic', Uint8Atomic);
+54 -54
src/shared/descriptors.ts
··· 9 9 import { Int64 } from './int64.ts'; 10 10 import { Uint64 } from './uint64.ts'; 11 11 import { Bool } from './bool.ts'; 12 - import { AtomicInt8 } from './atomic-int8.ts'; 13 - import { AtomicUint8 } from './atomic-uint8.ts'; 14 - import { AtomicInt16 } from './atomic-int16.ts'; 15 - import { AtomicUint16 } from './atomic-uint16.ts'; 16 - import { AtomicInt32 } from './atomic-int32.ts'; 17 - import { AtomicUint32 } from './atomic-uint32.ts'; 18 - import { AtomicInt64 } from './atomic-int64.ts'; 19 - import { AtomicUint64 } from './atomic-uint64.ts'; 20 - import { AtomicBool } from './atomic-bool.ts'; 12 + import { Int8Atomic } from './int8-atomic.ts'; 13 + import { Uint8Atomic } from './uint8-atomic.ts'; 14 + import { Int16Atomic } from './int16-atomic.ts'; 15 + import { Uint16Atomic } from './uint16-atomic.ts'; 16 + import { Int32Atomic } from './int32-atomic.ts'; 17 + import { Uint32Atomic } from './uint32-atomic.ts'; 18 + import { Int64Atomic } from './int64-atomic.ts'; 19 + import { Uint64Atomic } from './uint64-atomic.ts'; 20 + import { BoolAtomic } from './bool-atomic.ts'; 21 21 import { Mutex } from './mutex.ts'; 22 22 import { RwLock } from './rwlock.ts'; 23 23 ··· 62 62 ); 63 63 export const bool: Descriptor<Bool> = makeDescriptor(() => new Bool(), Bool.byteSize, Bool.byteAlignment, Bool); 64 64 65 - export const int8atomic: Descriptor<AtomicInt8> = makeDescriptor( 66 - () => new AtomicInt8(), 67 - AtomicInt8.byteSize, 68 - AtomicInt8.byteAlignment, 69 - AtomicInt8, 65 + export const int8atomic: Descriptor<Int8Atomic> = makeDescriptor( 66 + () => new Int8Atomic(), 67 + Int8Atomic.byteSize, 68 + Int8Atomic.byteAlignment, 69 + Int8Atomic, 70 70 ); 71 - export const uint8atomic: Descriptor<AtomicUint8> = makeDescriptor( 72 - () => new AtomicUint8(), 73 - AtomicUint8.byteSize, 74 - AtomicUint8.byteAlignment, 75 - AtomicUint8, 71 + export const uint8atomic: Descriptor<Uint8Atomic> = makeDescriptor( 72 + () => new Uint8Atomic(), 73 + Uint8Atomic.byteSize, 74 + Uint8Atomic.byteAlignment, 75 + Uint8Atomic, 76 76 ); 77 - export const int16atomic: Descriptor<AtomicInt16> = makeDescriptor( 78 - () => new AtomicInt16(), 79 - AtomicInt16.byteSize, 80 - AtomicInt16.byteAlignment, 81 - AtomicInt16, 77 + export const int16atomic: Descriptor<Int16Atomic> = makeDescriptor( 78 + () => new Int16Atomic(), 79 + Int16Atomic.byteSize, 80 + Int16Atomic.byteAlignment, 81 + Int16Atomic, 82 82 ); 83 - export const uint16atomic: Descriptor<AtomicUint16> = makeDescriptor( 84 - () => new AtomicUint16(), 85 - AtomicUint16.byteSize, 86 - AtomicUint16.byteAlignment, 87 - AtomicUint16, 83 + export const uint16atomic: Descriptor<Uint16Atomic> = makeDescriptor( 84 + () => new Uint16Atomic(), 85 + Uint16Atomic.byteSize, 86 + Uint16Atomic.byteAlignment, 87 + Uint16Atomic, 88 88 ); 89 - export const int32atomic: Descriptor<AtomicInt32> = makeDescriptor( 90 - () => new AtomicInt32(), 91 - AtomicInt32.byteSize, 92 - AtomicInt32.byteAlignment, 93 - AtomicInt32, 89 + export const int32atomic: Descriptor<Int32Atomic> = makeDescriptor( 90 + () => new Int32Atomic(), 91 + Int32Atomic.byteSize, 92 + Int32Atomic.byteAlignment, 93 + Int32Atomic, 94 94 ); 95 - export const uint32atomic: Descriptor<AtomicUint32> = makeDescriptor( 96 - () => new AtomicUint32(), 97 - AtomicUint32.byteSize, 98 - AtomicUint32.byteAlignment, 99 - AtomicUint32, 95 + export const uint32atomic: Descriptor<Uint32Atomic> = makeDescriptor( 96 + () => new Uint32Atomic(), 97 + Uint32Atomic.byteSize, 98 + Uint32Atomic.byteAlignment, 99 + Uint32Atomic, 100 100 ); 101 - export const int64atomic: Descriptor<AtomicInt64> = makeDescriptor( 102 - () => new AtomicInt64(), 103 - AtomicInt64.byteSize, 104 - AtomicInt64.byteAlignment, 105 - AtomicInt64, 101 + export const int64atomic: Descriptor<Int64Atomic> = makeDescriptor( 102 + () => new Int64Atomic(), 103 + Int64Atomic.byteSize, 104 + Int64Atomic.byteAlignment, 105 + Int64Atomic, 106 106 ); 107 - export const uint64atomic: Descriptor<AtomicUint64> = makeDescriptor( 108 - () => new AtomicUint64(), 109 - AtomicUint64.byteSize, 110 - AtomicUint64.byteAlignment, 111 - AtomicUint64, 107 + export const uint64atomic: Descriptor<Uint64Atomic> = makeDescriptor( 108 + () => new Uint64Atomic(), 109 + Uint64Atomic.byteSize, 110 + Uint64Atomic.byteAlignment, 111 + Uint64Atomic, 112 112 ); 113 - export const boolatomic: Descriptor<AtomicBool> = makeDescriptor( 114 - () => new AtomicBool(), 115 - AtomicBool.byteSize, 116 - AtomicBool.byteAlignment, 117 - AtomicBool, 113 + export const boolatomic: Descriptor<BoolAtomic> = makeDescriptor( 114 + () => new BoolAtomic(), 115 + BoolAtomic.byteSize, 116 + BoolAtomic.byteAlignment, 117 + BoolAtomic, 118 118 ); 119 119 120 120 export const mutex: Descriptor<Mutex> = makeDescriptor(() => new Mutex(), Mutex.byteSize, Mutex.byteAlignment, Mutex);
+9 -9
src/shared/index.ts
··· 34 34 export type { Int64 } from './int64.ts'; 35 35 export type { Uint64 } from './uint64.ts'; 36 36 export type { Bool } from './bool.ts'; 37 - export type { AtomicInt8 } from './atomic-int8.ts'; 38 - export type { AtomicUint8 } from './atomic-uint8.ts'; 39 - export type { AtomicInt16 } from './atomic-int16.ts'; 40 - export type { AtomicUint16 } from './atomic-uint16.ts'; 41 - export type { AtomicInt32 } from './atomic-int32.ts'; 42 - export type { AtomicUint32 } from './atomic-uint32.ts'; 43 - export type { AtomicInt64 } from './atomic-int64.ts'; 44 - export type { AtomicUint64 } from './atomic-uint64.ts'; 45 - export type { AtomicBool } from './atomic-bool.ts'; 37 + export type { Int8Atomic } from './int8-atomic.ts'; 38 + export type { Uint8Atomic } from './uint8-atomic.ts'; 39 + export type { Int16Atomic } from './int16-atomic.ts'; 40 + export type { Uint16Atomic } from './uint16-atomic.ts'; 41 + export type { Int32Atomic } from './int32-atomic.ts'; 42 + export type { Uint32Atomic } from './uint32-atomic.ts'; 43 + export type { Int64Atomic } from './int64-atomic.ts'; 44 + export type { Uint64Atomic } from './uint64-atomic.ts'; 45 + export type { BoolAtomic } from './bool-atomic.ts'; 46 46 export type { Mutex, MutexGuard } from './mutex.ts'; 47 47 export type { RwLock, ReadGuard, WriteGuard } from './rwlock.ts'; 48 48 export type { SharedStruct } from './shared-struct.ts';
+4 -4
test/fixtures/sync.ts
··· 1 1 import { mo } from 'moroutine'; 2 - import type { AtomicInt32, Mutex, RwLock } from 'moroutine'; 2 + import type { Int32Atomic, Mutex, RwLock } from 'moroutine'; 3 3 4 - export const atomicAdd = mo(import.meta, (counter: AtomicInt32, value: number): number => { 4 + export const atomicAdd = mo(import.meta, (counter: Int32Atomic, value: number): number => { 5 5 return counter.add(value); 6 6 }); 7 7 8 8 export const mutexIncrement = mo( 9 9 import.meta, 10 - async (mutex: Mutex, counter: AtomicInt32, times: number): Promise<void> => { 10 + async (mutex: Mutex, counter: Int32Atomic, times: number): Promise<void> => { 11 11 for (let i = 0; i < times; i++) { 12 12 const guard = await mutex.lock(); 13 13 const val = counter.load(); ··· 17 17 }, 18 18 ); 19 19 20 - export const rwlockRead = mo(import.meta, async (rwlock: RwLock, counter: AtomicInt32): Promise<number> => { 20 + export const rwlockRead = mo(import.meta, async (rwlock: RwLock, counter: Int32Atomic): Promise<number> => { 21 21 const guard = await rwlock.readLock(); 22 22 const val = counter.load(); 23 23 rwlock.readUnlock();
+1 -1
test/shared/atomic-bool.test.ts test/shared/bool-atomic.test.ts
··· 2 2 import assert from 'node:assert/strict'; 3 3 import { boolatomic } from 'moroutine'; 4 4 5 - describe('AtomicBool', () => { 5 + describe('BoolAtomic', () => { 6 6 it('self-allocates and initializes to false', () => { 7 7 const a = boolatomic(); 8 8 assert.equal(a.load(), false);
+1 -1
test/shared/atomic-int16.test.ts test/shared/int16-atomic.test.ts
··· 2 2 import assert from 'node:assert/strict'; 3 3 import { int16atomic } from 'moroutine'; 4 4 5 - describe('AtomicInt16', () => { 5 + describe('Int16Atomic', () => { 6 6 it('self-allocates and initializes to zero', () => { 7 7 const a = int16atomic(); 8 8 assert.equal(a.load(), 0);
+1 -1
test/shared/atomic-int32.test.ts test/shared/int32-atomic.test.ts
··· 2 2 import assert from 'node:assert/strict'; 3 3 import { int32atomic } from 'moroutine'; 4 4 5 - describe('AtomicInt32', () => { 5 + describe('Int32Atomic', () => { 6 6 it('self-allocates and initializes to zero', () => { 7 7 const a = int32atomic(); 8 8 assert.equal(a.load(), 0);
+1 -1
test/shared/atomic-int64.test.ts test/shared/int64-atomic.test.ts
··· 2 2 import assert from 'node:assert/strict'; 3 3 import { int64atomic } from 'moroutine'; 4 4 5 - describe('AtomicInt64', () => { 5 + describe('Int64Atomic', () => { 6 6 it('self-allocates and initializes to zero', () => { 7 7 const a = int64atomic(); 8 8 assert.equal(a.load(), 0n);
+1 -1
test/shared/atomic-int8.test.ts test/shared/int8-atomic.test.ts
··· 2 2 import assert from 'node:assert/strict'; 3 3 import { int8atomic } from 'moroutine'; 4 4 5 - describe('AtomicInt8', () => { 5 + describe('Int8Atomic', () => { 6 6 it('self-allocates and initializes to zero', () => { 7 7 const a = int8atomic(); 8 8 assert.equal(a.load(), 0);
+1 -1
test/shared/atomic-uint16.test.ts test/shared/uint16-atomic.test.ts
··· 2 2 import assert from 'node:assert/strict'; 3 3 import { uint16atomic } from 'moroutine'; 4 4 5 - describe('AtomicUint16', () => { 5 + describe('Uint16Atomic', () => { 6 6 it('self-allocates and initializes to zero', () => { 7 7 const a = uint16atomic(); 8 8 assert.equal(a.load(), 0);
+1 -1
test/shared/atomic-uint32.test.ts test/shared/uint32-atomic.test.ts
··· 2 2 import assert from 'node:assert/strict'; 3 3 import { uint32atomic } from 'moroutine'; 4 4 5 - describe('AtomicUint32', () => { 5 + describe('Uint32Atomic', () => { 6 6 it('self-allocates and initializes to zero', () => { 7 7 const a = uint32atomic(); 8 8 assert.equal(a.load(), 0);
+1 -1
test/shared/atomic-uint64.test.ts test/shared/uint64-atomic.test.ts
··· 2 2 import assert from 'node:assert/strict'; 3 3 import { uint64atomic } from 'moroutine'; 4 4 5 - describe('AtomicUint64', () => { 5 + describe('Uint64Atomic', () => { 6 6 it('self-allocates and initializes to zero', () => { 7 7 const a = uint64atomic(); 8 8 assert.equal(a.load(), 0n);
+1 -1
test/shared/atomic-uint8.test.ts test/shared/uint8-atomic.test.ts
··· 2 2 import assert from 'node:assert/strict'; 3 3 import { uint8atomic } from 'moroutine'; 4 4 5 - describe('AtomicUint8', () => { 5 + describe('Uint8Atomic', () => { 6 6 it('self-allocates and initializes to zero', () => { 7 7 const a = uint8atomic(); 8 8 assert.equal(a.load(), 0);
+1 -1
test/shared/cross-worker.test.ts
··· 5 5 import { readValue, writeValue } from '../fixtures/shared-new.ts'; 6 6 7 7 describe('shared primitives across workers', () => { 8 - it('AtomicInt32 is shared across worker threads', async () => { 8 + it('Int32Atomic is shared across worker threads', async () => { 9 9 const counter = int32atomic(); 10 10 const pool = workerPool(2); 11 11 try {