Offload functions to worker threads with shared memory primitives for Node.js.
1import { Bytes } from './bytes.ts';
2import { SharedString } from './string.ts';
3import { Int8 } from './int8.ts';
4import { Uint8 } from './uint8.ts';
5import { Int16 } from './int16.ts';
6import { Uint16 } from './uint16.ts';
7import { Int32 } from './int32.ts';
8import { Uint32 } from './uint32.ts';
9import { Int64 } from './int64.ts';
10import { Uint64 } from './uint64.ts';
11import { Bool } from './bool.ts';
12import { Int8Atomic } from './int8-atomic.ts';
13import { Uint8Atomic } from './uint8-atomic.ts';
14import { Int16Atomic } from './int16-atomic.ts';
15import { Uint16Atomic } from './uint16-atomic.ts';
16import { Int32Atomic } from './int32-atomic.ts';
17import { Uint32Atomic } from './uint32-atomic.ts';
18import { Int64Atomic } from './int64-atomic.ts';
19import { Uint64Atomic } from './uint64-atomic.ts';
20import { BoolAtomic } from './bool-atomic.ts';
21import { Mutex } from './mutex.ts';
22import { RwLock } from './rwlock.ts';
23
24/** A schema token describing a shared-memory type. Callable to create a standalone instance. */
25export interface Descriptor<T> {
26 (): T;
27 byteSize: number;
28 byteAlignment: number;
29 _class: new (buffer: SharedArrayBuffer, byteOffset: number) => T;
30}
31
32function makeDescriptor<T>(
33 factory: () => T,
34 byteSize: number,
35 byteAlignment: number,
36 _class: new (buffer: SharedArrayBuffer, byteOffset: number) => T,
37): Descriptor<T> {
38 return Object.assign(factory, { byteSize, byteAlignment, _class });
39}
40
41/** Non-atomic shared primitives. Use inside a lock for thread safety. */
42export const int8: Descriptor<Int8> = makeDescriptor(() => new Int8(), Int8.byteSize, Int8.byteAlignment, Int8);
43export const uint8: Descriptor<Uint8> = makeDescriptor(() => new Uint8(), Uint8.byteSize, Uint8.byteAlignment, Uint8);
44export const int16: Descriptor<Int16> = makeDescriptor(() => new Int16(), Int16.byteSize, Int16.byteAlignment, Int16);
45export const uint16: Descriptor<Uint16> = makeDescriptor(
46 () => new Uint16(),
47 Uint16.byteSize,
48 Uint16.byteAlignment,
49 Uint16,
50);
51export const int32: Descriptor<Int32> = makeDescriptor(() => new Int32(), Int32.byteSize, Int32.byteAlignment, Int32);
52export const uint32: Descriptor<Uint32> = makeDescriptor(
53 () => new Uint32(),
54 Uint32.byteSize,
55 Uint32.byteAlignment,
56 Uint32,
57);
58export const int64: Descriptor<Int64> = makeDescriptor(() => new Int64(), Int64.byteSize, Int64.byteAlignment, Int64);
59export const uint64: Descriptor<Uint64> = makeDescriptor(
60 () => new Uint64(),
61 Uint64.byteSize,
62 Uint64.byteAlignment,
63 Uint64,
64);
65export const bool: Descriptor<Bool> = makeDescriptor(() => new Bool(), Bool.byteSize, Bool.byteAlignment, Bool);
66
67/** Atomic shared primitives. Thread-safe without a lock. */
68export const int8atomic: Descriptor<Int8Atomic> = makeDescriptor(
69 () => new Int8Atomic(),
70 Int8Atomic.byteSize,
71 Int8Atomic.byteAlignment,
72 Int8Atomic,
73);
74export const uint8atomic: Descriptor<Uint8Atomic> = makeDescriptor(
75 () => new Uint8Atomic(),
76 Uint8Atomic.byteSize,
77 Uint8Atomic.byteAlignment,
78 Uint8Atomic,
79);
80export const int16atomic: Descriptor<Int16Atomic> = makeDescriptor(
81 () => new Int16Atomic(),
82 Int16Atomic.byteSize,
83 Int16Atomic.byteAlignment,
84 Int16Atomic,
85);
86export const uint16atomic: Descriptor<Uint16Atomic> = makeDescriptor(
87 () => new Uint16Atomic(),
88 Uint16Atomic.byteSize,
89 Uint16Atomic.byteAlignment,
90 Uint16Atomic,
91);
92export const int32atomic: Descriptor<Int32Atomic> = makeDescriptor(
93 () => new Int32Atomic(),
94 Int32Atomic.byteSize,
95 Int32Atomic.byteAlignment,
96 Int32Atomic,
97);
98export const uint32atomic: Descriptor<Uint32Atomic> = makeDescriptor(
99 () => new Uint32Atomic(),
100 Uint32Atomic.byteSize,
101 Uint32Atomic.byteAlignment,
102 Uint32Atomic,
103);
104export const int64atomic: Descriptor<Int64Atomic> = makeDescriptor(
105 () => new Int64Atomic(),
106 Int64Atomic.byteSize,
107 Int64Atomic.byteAlignment,
108 Int64Atomic,
109);
110export const uint64atomic: Descriptor<Uint64Atomic> = makeDescriptor(
111 () => new Uint64Atomic(),
112 Uint64Atomic.byteSize,
113 Uint64Atomic.byteAlignment,
114 Uint64Atomic,
115);
116export const boolatomic: Descriptor<BoolAtomic> = makeDescriptor(
117 () => new BoolAtomic(),
118 BoolAtomic.byteSize,
119 BoolAtomic.byteAlignment,
120 BoolAtomic,
121);
122
123/** Shared-memory locks. */
124export const mutex: Descriptor<Mutex> = makeDescriptor(() => new Mutex(), Mutex.byteSize, Mutex.byteAlignment, Mutex);
125export const rwlock: Descriptor<RwLock> = makeDescriptor(
126 () => new RwLock(),
127 RwLock.byteSize,
128 RwLock.byteAlignment,
129 RwLock,
130);
131
132export interface BytesDescriptor extends Bytes {
133 byteSize: number;
134 byteAlignment: number;
135 _class: typeof Bytes;
136 _size: number;
137}
138
139/**
140 * Creates a fixed-size shared byte buffer. Acts as both a standalone factory and a schema descriptor.
141 * @param size - The buffer capacity in bytes.
142 * @returns A {@link Bytes} instance with descriptor metadata for use with `shared()`.
143 */
144export function bytes(size: number): BytesDescriptor {
145 const instance = new Bytes(size);
146 return Object.assign(instance, {
147 byteSize: size,
148 byteAlignment: Bytes.byteAlignment,
149 _class: Bytes,
150 _size: size,
151 }) as BytesDescriptor;
152}
153
154export interface StringDescriptor extends SharedString {
155 byteSize: number;
156 byteAlignment: number;
157 _class: typeof SharedString;
158 _maxBytes: number;
159}
160
161/**
162 * Creates a variable-length shared UTF-8 string with a max byte length. Acts as both a standalone factory and a schema descriptor.
163 * @param maxBytes - Maximum number of bytes for the encoded string.
164 * @returns A {@link SharedString} instance with descriptor metadata for use with `shared()`.
165 */
166export function string(maxBytes: number): StringDescriptor {
167 const instance = new SharedString(maxBytes);
168 return Object.assign(instance, {
169 byteSize: 4 + maxBytes,
170 byteAlignment: SharedString.byteAlignment,
171 _class: SharedString,
172 _maxBytes: maxBytes,
173 }) as StringDescriptor;
174}