sharedthread 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,976 @@
1
+ // src/index.ts
2
+ import { isMainThread as isMainThread2 } from "worker_threads";
3
+
4
+ // src/Memory/TypeRegistry.ts
5
+ var TypeRegistry = class _TypeRegistry {
6
+ static indexToType = /* @__PURE__ */ new Map();
7
+ static typeToIndex = /* @__PURE__ */ new Map();
8
+ static hashToType = /* @__PURE__ */ new Map();
9
+ static typeToHash = /* @__PURE__ */ new Map();
10
+ static indexToHash = new Uint32Array(0);
11
+ // private static cyrb53(str: string, seed: number = 0): number {
12
+ // let h1 = 0xdeadbeef ^ seed;
13
+ // let h2 = 0x41c6ce57 ^ seed;
14
+ // for (let i = 0, ch: number; i < str.length; i++) {
15
+ // ch = str.charCodeAt(i);
16
+ // h1 = Math.imul(h1 ^ ch, 2654435761);
17
+ // h2 = Math.imul(h2 ^ ch, 1597334677);
18
+ // }
19
+ // h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507);
20
+ // h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909);
21
+ // h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507);
22
+ // h2 ^= Math.imul(h1 ^ (h1 >>> 13), 3266489909);
23
+ // // Combine the two 32-bit hashes into a single 53-bit unsigned integer
24
+ // return 4294967296 * (2097151 & h2) + (h1 >>> 0);
25
+ // }
26
+ static fnv1(str) {
27
+ let hash = 2166136261;
28
+ for (let i = 0; i < str.length; i++) {
29
+ hash ^= str.charCodeAt(i);
30
+ hash = Math.imul(hash, 16777619);
31
+ }
32
+ return hash >>> 0;
33
+ }
34
+ static registerType(dataType) {
35
+ if (this.typeToIndex.has(dataType)) throw new Error("class is alreadly registered");
36
+ let idx = _TypeRegistry.indexToType.size;
37
+ let hash;
38
+ do {
39
+ hash = _TypeRegistry.fnv1(dataType.toString());
40
+ } while (_TypeRegistry.hashToType.has(hash));
41
+ _TypeRegistry.indexToType.set(idx, dataType);
42
+ _TypeRegistry.typeToIndex.set(dataType, idx);
43
+ _TypeRegistry.hashToType.set(hash, dataType);
44
+ _TypeRegistry.typeToHash.set(dataType, hash);
45
+ let nextHashes = new Uint32Array(idx + 1);
46
+ nextHashes.set(_TypeRegistry.indexToHash);
47
+ nextHashes[idx] = hash;
48
+ _TypeRegistry.indexToHash = nextHashes;
49
+ dataType.typeID = idx;
50
+ return idx;
51
+ }
52
+ static getTypeBuffer() {
53
+ return new Uint32Array(_TypeRegistry.indexToHash).buffer;
54
+ }
55
+ static verifyTypeBuffer(typeBuffer) {
56
+ const arrayEqual = (a, b) => a.length == b.length && a.every((v, i) => v == b[i]);
57
+ const setEqual = (a, b) => a.length === b.length && ((m) => a.every((x) => m.set(x, (m.get(x) || 0) + 1)) && b.every((x) => m.get(x) && m.set(x, m.get(x) - 1)))(/* @__PURE__ */ new Map());
58
+ let hashArray = new Uint32Array(typeBuffer);
59
+ let isEqual = arrayEqual(this.indexToHash, hashArray);
60
+ let isSetEqual = setEqual(this.indexToHash, hashArray);
61
+ if (!isEqual) {
62
+ if (isSetEqual) {
63
+ throw new Error("type registrations are out of order");
64
+ } else {
65
+ throw new Error("type registrations mismatched");
66
+ }
67
+ }
68
+ }
69
+ static getTypeByIndex(index) {
70
+ if (!this.indexToType.has(index)) throw new Error("cannot find type by index");
71
+ return this.indexToType.get(index);
72
+ }
73
+ static getTypeByHash(hash) {
74
+ if (!this.hashToType.has(hash)) throw new Error("cannot find type by hash");
75
+ return this.hashToType.get(hash);
76
+ }
77
+ static getIndexByType(type) {
78
+ if (!this.typeToIndex.has(type)) throw new Error("cannot find id by type");
79
+ return this.typeToIndex.get(type);
80
+ }
81
+ static getHashByType(type) {
82
+ if (!this.typeToHash.has(type)) throw new Error("cannot find hash by index");
83
+ return this.typeToHash.get(type);
84
+ }
85
+ constructor() {
86
+ }
87
+ };
88
+
89
+ // src/Memory/SharedHeap.ts
90
+ var SharedHeap = class _SharedHeap {
91
+ static heaps = [];
92
+ static getHeapByID(i) {
93
+ if (_SharedHeap.heaps[i] === void 0) throw new Error(`cannot find heap with heapID`);
94
+ return _SharedHeap.heaps[i];
95
+ }
96
+ _heapID;
97
+ _heapSize;
98
+ _buffer;
99
+ _view;
100
+ // Bit-Packing Constants for the Lower 32-bit Header
101
+ static SHIFT_TYPEID = 0;
102
+ static SHIFT_ARRAY = 23;
103
+ static SHIFT_PTR = 26;
104
+ static SHIFT_ALLOC = 29;
105
+ static MASK_TYPEID = 8388607;
106
+ // 23 bits
107
+ static MASK_ARRAY = 7;
108
+ // 3 bits
109
+ static MASK_PTR = 7;
110
+ // 3 bits
111
+ static MASK_ALLOC = 7;
112
+ // 3 bits
113
+ constructor(b, heapID = _SharedHeap.heaps.length) {
114
+ if (_SharedHeap.heaps[heapID] !== void 0) throw new Error("heap assignment overlap");
115
+ this._heapID = heapID;
116
+ _SharedHeap.heaps[this._heapID] = this;
117
+ if (b instanceof SharedArrayBuffer) {
118
+ this._heapSize = b.byteLength;
119
+ this._buffer = b;
120
+ this._view = new DataView(this._buffer);
121
+ } else {
122
+ this._heapSize = b + 4 + 3 & ~3;
123
+ this._buffer = new SharedArrayBuffer(this._heapSize);
124
+ this._view = new DataView(this._buffer);
125
+ this.listHead = -1;
126
+ const initialPayloadSize = this._heapSize - 4 - 8;
127
+ this.writeHeader(4, initialPayloadSize, 0, 0, 0, 0);
128
+ this._view.setInt32(12, -1, true);
129
+ this._view.setInt32(16, -1, true);
130
+ this.syncFreeList();
131
+ }
132
+ }
133
+ get heapID() {
134
+ return this._heapID;
135
+ }
136
+ get view() {
137
+ return this._view;
138
+ }
139
+ get heapSize() {
140
+ return this._heapSize;
141
+ }
142
+ get buffer() {
143
+ return this._buffer;
144
+ }
145
+ // Dynamically reads and writes to the beginning of the SharedArrayBuffer
146
+ get listHead() {
147
+ return this._view.getInt32(0, true);
148
+ }
149
+ set listHead(offset) {
150
+ this._view.setInt32(0, offset, true);
151
+ }
152
+ // --- Fixed Dual 32-Bit Bit-Packing Utilities ---
153
+ getHeaderSize(offset) {
154
+ return this._view.getUint32(offset, true);
155
+ }
156
+ getHeaderAllocated(offset) {
157
+ const lowerHeader = this._view.getUint32(offset + 4, true);
158
+ return lowerHeader >>> _SharedHeap.SHIFT_ALLOC & _SharedHeap.MASK_ALLOC;
159
+ }
160
+ writeHeader(offset, size, alloc, ptr, array, typeID) {
161
+ if (typeID < 0 || typeID > _SharedHeap.MASK_TYPEID) throw new Error("typeID out of bounds");
162
+ if (size < 0 || size > 4294967295) throw new Error("size exceeds 32-bit limit");
163
+ if (alloc < 0 || alloc > 7 || ptr < 0 || ptr > 7 || array < 0 || array > 7) throw new Error("alloc, ptr, and array must fit in 3 bits (0-7)");
164
+ this._view.setUint32(offset, size, true);
165
+ const lowerHeader = (alloc & _SharedHeap.MASK_ALLOC) << _SharedHeap.SHIFT_ALLOC | (ptr & _SharedHeap.MASK_PTR) << _SharedHeap.SHIFT_PTR | (array & _SharedHeap.MASK_ARRAY) << _SharedHeap.SHIFT_ARRAY | (typeID & _SharedHeap.MASK_TYPEID) << _SharedHeap.SHIFT_TYPEID;
166
+ this._view.setUint32(offset + 4, lowerHeader >>> 0, true);
167
+ }
168
+ syncFreeList() {
169
+ let current = 4;
170
+ this.listHead = -1;
171
+ let lastFree = -1;
172
+ while (current < this._heapSize) {
173
+ const size = this.getHeaderSize(current);
174
+ const allocVal = this.getHeaderAllocated(current);
175
+ if (allocVal === 0) {
176
+ if (this.listHead === -1) {
177
+ this.listHead = current;
178
+ }
179
+ if (lastFree !== -1) {
180
+ this._view.setInt32(lastFree + 8, current, true);
181
+ this._view.setInt32(current + 12, lastFree, true);
182
+ }
183
+ lastFree = current;
184
+ }
185
+ current += 8 + size;
186
+ }
187
+ if (lastFree !== -1) {
188
+ this._view.setInt32(lastFree + 8, -1, true);
189
+ }
190
+ }
191
+ allocate(requestedSize, typeID, isPtr = false, isArray = false) {
192
+ if (isNaN(requestedSize)) throw new Error("cannot allocate NaN size");
193
+ if (requestedSize <= 0) throw new Error("cannot allocate negative size");
194
+ const allocValue = 1;
195
+ const ptrValue = isPtr ? 1 : 0;
196
+ const arrayValue = isArray ? 1 : 0;
197
+ const alignedSize = Math.max(requestedSize + 3 & ~3, 4);
198
+ let currentOffset = this.listHead;
199
+ while (currentOffset !== -1) {
200
+ const size = this.getHeaderSize(currentOffset);
201
+ if (size >= alignedSize) {
202
+ const remainingSpace = size - alignedSize - 8;
203
+ if (remainingSpace >= 12) {
204
+ const nextFreeOffset = currentOffset + 8 + alignedSize;
205
+ this.replaceFreeNode(currentOffset, nextFreeOffset);
206
+ this.writeHeader(currentOffset, alignedSize, allocValue, ptrValue, arrayValue, typeID);
207
+ this.writeHeader(nextFreeOffset, remainingSpace, 0, 0, 0, 0);
208
+ } else {
209
+ this.removeFreeNode(currentOffset);
210
+ this.writeHeader(currentOffset, size, allocValue, ptrValue, arrayValue, typeID);
211
+ }
212
+ return currentOffset + 8;
213
+ }
214
+ currentOffset = this._view.getInt32(currentOffset + 8, true);
215
+ }
216
+ throw new Error("heap out of memory");
217
+ }
218
+ free(ptr) {
219
+ if (ptr < 12 || ptr >= this._heapSize) throw new Error("cannot free out of bounds");
220
+ const headerOffset = ptr - 8;
221
+ const size = this.getHeaderSize(headerOffset);
222
+ this.writeHeader(headerOffset, size, 0, 0, 0, 0);
223
+ this.addFreeNodeToFront(headerOffset);
224
+ }
225
+ addFreeNodeToFront(offset) {
226
+ const oldHead = this.listHead;
227
+ this.listHead = offset;
228
+ this._view.setInt32(offset + 8, oldHead, true);
229
+ this._view.setInt32(offset + 12, -1, true);
230
+ if (oldHead !== -1) {
231
+ this._view.setInt32(oldHead + 12, offset, true);
232
+ }
233
+ }
234
+ // --- Public External Metadata Readers (Accepts Pointer Address, Reads Header) ---
235
+ getTypeIDAt(ptr) {
236
+ if (ptr < 12 || ptr >= this._heapSize) return 0;
237
+ const lowerHeader = this._view.getUint32(ptr - 4, true);
238
+ return lowerHeader >>> _SharedHeap.SHIFT_TYPEID & _SharedHeap.MASK_TYPEID;
239
+ }
240
+ getAllocAt(ptr) {
241
+ if (ptr < 12 || ptr >= this._heapSize) return 0;
242
+ const lowerHeader = this._view.getUint32(ptr - 4, true);
243
+ return lowerHeader >>> _SharedHeap.SHIFT_ALLOC & _SharedHeap.MASK_ALLOC;
244
+ }
245
+ getPtrAt(ptr) {
246
+ if (ptr < 12 || ptr >= this._heapSize) return 0;
247
+ const lowerHeader = this._view.getUint32(ptr - 4, true);
248
+ return lowerHeader >>> _SharedHeap.SHIFT_PTR & _SharedHeap.MASK_PTR;
249
+ }
250
+ getArrayAt(ptr) {
251
+ if (ptr < 12 || ptr >= this._heapSize) return 0;
252
+ const lowerHeader = this._view.getUint32(ptr - 4, true);
253
+ return lowerHeader >>> _SharedHeap.SHIFT_ARRAY & _SharedHeap.MASK_ARRAY;
254
+ }
255
+ // --- Private Free-List Node Handlers ---
256
+ removeFreeNode(offset) {
257
+ const next = this._view.getInt32(offset + 8, true);
258
+ const prev = this._view.getInt32(offset + 12, true);
259
+ if (prev !== -1) this._view.setInt32(prev + 8, next, true);
260
+ else this.listHead = next;
261
+ if (next !== -1) this._view.setInt32(next + 12, prev, true);
262
+ }
263
+ replaceFreeNode(oldOffset, newOffset) {
264
+ const next = this._view.getInt32(oldOffset + 8, true);
265
+ const prev = this._view.getInt32(oldOffset + 12, true);
266
+ if (next !== -1) this._view.setInt32(next + 12, newOffset, true);
267
+ if (prev !== -1) this._view.setInt32(prev + 8, newOffset, true);
268
+ else this.listHead = newOffset;
269
+ this._view.setInt32(newOffset + 8, next, true);
270
+ this._view.setInt32(newOffset + 12, prev, true);
271
+ }
272
+ };
273
+
274
+ // src/Memory/SharedType.ts
275
+ var SharedType = class {
276
+ _addr;
277
+ _heap;
278
+ constructor(heap, addr) {
279
+ if (!isFinite(addr) || addr < 0) throw new Error("invalid address");
280
+ this._heap = heap;
281
+ this._addr = addr;
282
+ }
283
+ get addr() {
284
+ return this._addr;
285
+ }
286
+ get heap() {
287
+ return this._heap;
288
+ }
289
+ };
290
+
291
+ // src/Memory/SharedPrimitive.ts
292
+ var SharedPrimitive = class extends SharedType {
293
+ static typeID;
294
+ static byteSize;
295
+ static isPtr = false;
296
+ static isArr = false;
297
+ };
298
+
299
+ // src/Memory/SharedReference.ts
300
+ var SharedReference = class extends SharedType {
301
+ static typeID;
302
+ static isPtr = false;
303
+ static isArr = false;
304
+ };
305
+
306
+ // src/Memory/SharedPointer.ts
307
+ var SharedPointer = class _SharedPointer extends SharedPrimitive {
308
+ static byteSize = 4;
309
+ static isPtr = true;
310
+ static fromData(heap, v) {
311
+ let addr = heap.allocate(_SharedPointer.byteSize, v.type.typeID, _SharedPointer.isPtr);
312
+ let obj = new _SharedPointer(heap, addr);
313
+ if (v.addr) obj.value = addr;
314
+ return obj;
315
+ }
316
+ _heldType;
317
+ _deref = null;
318
+ constructor(heap, addr, dataType) {
319
+ super(heap, addr);
320
+ this._heldType = dataType ?? TypeRegistry.getTypeByIndex(heap.getTypeIDAt(addr));
321
+ }
322
+ get heldType() {
323
+ return this._heldType;
324
+ }
325
+ get addr() {
326
+ return this._addr;
327
+ }
328
+ get heap() {
329
+ return this._heap;
330
+ }
331
+ set value(p) {
332
+ this._heap.view.setUint32(this._addr, p);
333
+ if (this.heap.getArrayAt(p)) {
334
+ if (this._heldType != SharedArray) throw new Error("pointer points to wrong type");
335
+ } else {
336
+ if (this._heldType != TypeRegistry.getTypeByIndex(this._heap.getTypeIDAt(this._addr))) throw new Error("pointer points to wrong type");
337
+ }
338
+ this._deref = new this._heldType(this._heap, p);
339
+ }
340
+ get value() {
341
+ return this._heap.view.getUint32(this._addr);
342
+ }
343
+ set deref(v) {
344
+ if (!(v instanceof this._heldType)) throw new Error("assigned wrong type to pointer");
345
+ this.value = v.addr;
346
+ this._deref = v;
347
+ }
348
+ get deref() {
349
+ return this._deref;
350
+ }
351
+ };
352
+
353
+ // src/Memory/SharedUint32.ts
354
+ function Uint32(value) {
355
+ if (!Number.isInteger(value) || value < -2147483648 || value > 2147483647) {
356
+ throw new RangeError("cannot cast value to uint32");
357
+ }
358
+ return value;
359
+ }
360
+ var SharedUint32 = class _SharedUint32 extends SharedPrimitive {
361
+ static byteSize = 4;
362
+ static fromData(heap, v) {
363
+ let addr = heap.allocate(_SharedUint32.byteSize, _SharedUint32.typeID);
364
+ let obj = new _SharedUint32(heap, addr);
365
+ obj.value = v;
366
+ return obj;
367
+ }
368
+ set value(v) {
369
+ this._heap.view.setUint32(this._addr, Uint32(v));
370
+ }
371
+ get value() {
372
+ return this._heap.view.getUint32(this._addr);
373
+ }
374
+ };
375
+ TypeRegistry.registerType(SharedUint32);
376
+
377
+ // src/Memory/SharedArray.ts
378
+ var SharedArray = class extends SharedReference {
379
+ static isArr = true;
380
+ static properties = {
381
+ length: { type: SharedUint32 }
382
+ };
383
+ static fromData(heap, v) {
384
+ let length = v.length;
385
+ let type = v.type;
386
+ if (type.prototype instanceof SharedPrimitive) {
387
+ type = type;
388
+ } else {
389
+ type = SharedPointer;
390
+ }
391
+ let elementSize = type.byteSize;
392
+ let totalSize = 4 + elementSize * length;
393
+ let addr = heap.allocate(totalSize, type.typeID, false, true);
394
+ heap.view.setUint32(addr, length);
395
+ let obj = new this(heap, addr);
396
+ if (v.array) {
397
+ for (let i = 0; i < length; i++) {
398
+ obj.elements[i] = v.array[i];
399
+ }
400
+ }
401
+ return obj;
402
+ }
403
+ _heldType;
404
+ _elementType;
405
+ _elementSize;
406
+ _byteSize;
407
+ _length;
408
+ elements = [];
409
+ constructor(heap, addr) {
410
+ super(heap, addr);
411
+ this._elementType = TypeRegistry.getTypeByIndex(heap.getTypeIDAt(addr));
412
+ this._heldType = heap.getPtrAt(addr) ? SharedPointer : this._elementType;
413
+ this._elementSize = this._heldType.byteSize;
414
+ this._length = heap.view.getUint32(addr);
415
+ this._byteSize = 4 + this._elementSize * this._length;
416
+ let offset = 4;
417
+ for (let i = 0; i < this._length; i++, offset += this._elementSize) {
418
+ this.elements.push(new this._heldType(heap, addr + offset));
419
+ }
420
+ return new Proxy(this, {
421
+ get(target, prop, receiver) {
422
+ if (Number.isInteger(Number(prop)) && prop >= 0 && prop < target._length) {
423
+ return target.elements[prop];
424
+ }
425
+ return Reflect.get(target, prop, receiver);
426
+ },
427
+ set(target, prop, value, receiver) {
428
+ if (typeof prop == "number" && prop >= 0 && prop < target._length) {
429
+ if (target.elements[prop] && "value" in target.elements[prop]) {
430
+ target.elements[prop].value = value;
431
+ return true;
432
+ }
433
+ }
434
+ return Reflect.set(target, prop, value, receiver);
435
+ }
436
+ });
437
+ }
438
+ get addr() {
439
+ return this._addr;
440
+ }
441
+ get heap() {
442
+ return this._heap;
443
+ }
444
+ get heldType() {
445
+ return this._heldType;
446
+ }
447
+ get elementType() {
448
+ return this._elementType;
449
+ }
450
+ get elementSize() {
451
+ return this._elementSize;
452
+ }
453
+ static get byteSize() {
454
+ throw new Error("cannot precalculate array size");
455
+ }
456
+ get byteSize() {
457
+ return this._byteSize;
458
+ }
459
+ get length() {
460
+ return this._length;
461
+ }
462
+ };
463
+
464
+ // src/Memory/SharedInt32.ts
465
+ function Int32(value) {
466
+ if (!Number.isInteger(value) || value < -2147483648 || value > 2147483647) {
467
+ throw new RangeError("cannot cast value to int32");
468
+ }
469
+ return value;
470
+ }
471
+ var SharedInt32 = class _SharedInt32 extends SharedPrimitive {
472
+ static byteSize = 4;
473
+ static fromData(heap, v) {
474
+ let addr = heap.allocate(_SharedInt32.byteSize, _SharedInt32.typeID);
475
+ let obj = new _SharedInt32(heap, addr);
476
+ obj.value = v;
477
+ return obj;
478
+ }
479
+ set value(v) {
480
+ this._heap.view.setInt32(this._addr, Int32(v));
481
+ }
482
+ get value() {
483
+ return this._heap.view.getInt32(this._addr);
484
+ }
485
+ };
486
+ TypeRegistry.registerType(SharedInt32);
487
+
488
+ // src/Memory/SharedStruct.ts
489
+ var SharedStruct = class _SharedStruct extends SharedReference {
490
+ static fromData(heap, param) {
491
+ let addr = heap.allocate(this.byteSize, this.typeID);
492
+ let obj = new this(heap, addr);
493
+ obj.imprint(param);
494
+ return obj;
495
+ }
496
+ static properties;
497
+ _byteSize = 0;
498
+ properties = {};
499
+ constructor(heap, addr) {
500
+ super(heap, addr);
501
+ const prop = this.constructor.properties;
502
+ for (let key in prop) {
503
+ let dataDeclaration = prop[key];
504
+ let dataType = dataDeclaration.type;
505
+ let params = dataDeclaration.param;
506
+ let data;
507
+ let propSize;
508
+ if (SharedPrimitive.isPrototypeOf(dataType)) {
509
+ dataType = dataType;
510
+ if (dataType == SharedPointer) {
511
+ data = new SharedPointer(heap, addr + this._byteSize, params.type);
512
+ propSize = SharedPointer.byteSize;
513
+ } else {
514
+ data = new dataType(heap, addr + this._byteSize);
515
+ if (params !== void 0) data.value = params;
516
+ propSize = dataType.byteSize;
517
+ }
518
+ } else if ("type" in dataDeclaration && "param" in dataDeclaration) {
519
+ data = dataDeclaration.type.fromData(heap, dataDeclaration.param);
520
+ let p = new SharedPointer(heap, addr + this._byteSize, dataDeclaration.type);
521
+ propSize = SharedPointer.byteSize;
522
+ p.value = data.addr;
523
+ data = p;
524
+ } else {
525
+ throw new Error("invalid declaration");
526
+ }
527
+ this._byteSize += propSize;
528
+ this.properties[key] = data;
529
+ }
530
+ queueMicrotask(() => {
531
+ Object.preventExtensions(this);
532
+ });
533
+ return new Proxy(this, {
534
+ get(target, prop2, receiver) {
535
+ if (prop2 in target.properties) {
536
+ let v = target.properties[prop2];
537
+ return v;
538
+ }
539
+ return Reflect.get(target, prop2, receiver);
540
+ }
541
+ });
542
+ }
543
+ imprint(obj) {
544
+ if (obj == void 0) return;
545
+ for (let key in obj) {
546
+ if (key in this.properties) {
547
+ let ref = this.properties[key];
548
+ if (ref instanceof _SharedStruct) {
549
+ ref.imprint(obj[key]);
550
+ } else if (ref instanceof SharedPrimitive) {
551
+ ref.value = obj[key];
552
+ }
553
+ }
554
+ }
555
+ }
556
+ static get byteSize() {
557
+ let size = 0;
558
+ let properties = this.properties;
559
+ for (let key in properties) {
560
+ let declaration = properties[key];
561
+ let dataType = declaration.type;
562
+ if (SharedPrimitive.isPrototypeOf(dataType)) {
563
+ size += dataType.byteSize;
564
+ } else {
565
+ size += SharedPointer.byteSize;
566
+ }
567
+ }
568
+ return size;
569
+ }
570
+ get byteSize() {
571
+ let size = 0;
572
+ let properties = this.constructor.properties;
573
+ for (let key in properties) {
574
+ let declaration = properties[key];
575
+ let dataType = declaration.type;
576
+ if (SharedPrimitive.isPrototypeOf(dataType)) {
577
+ size += dataType.byteSize;
578
+ } else {
579
+ size += SharedPointer.byteSize;
580
+ }
581
+ }
582
+ return size;
583
+ }
584
+ };
585
+
586
+ // src/Threads/MainThread.ts
587
+ import { threadId, threadName, Worker } from "worker_threads";
588
+
589
+ // src/Threads/Thread.ts
590
+ import { EventEmitter } from "events";
591
+ import { postMessageToThread } from "worker_threads";
592
+ var Thread = class extends EventEmitter {
593
+ static async sendToThread(threadId3, data, label = null) {
594
+ if (!data) return;
595
+ return postMessageToThread(threadId3, {
596
+ tag: "message",
597
+ label,
598
+ data
599
+ });
600
+ }
601
+ static async transferToThread(threadId3, data, transferList, label = null) {
602
+ if (!data) return;
603
+ return postMessageToThread(threadId3, {
604
+ tag: "message",
605
+ label,
606
+ data
607
+ }, transferList);
608
+ }
609
+ port;
610
+ config;
611
+ constructor(port, config = {}) {
612
+ super();
613
+ this.port = port;
614
+ this.config = config;
615
+ }
616
+ send(data, label = null) {
617
+ if (!data) return;
618
+ this.port.postMessage({
619
+ tag: "message",
620
+ label,
621
+ data
622
+ });
623
+ }
624
+ sendWithTransfer(data, transferList, label = null) {
625
+ if (!data) return;
626
+ this.port.postMessage({
627
+ tag: "message",
628
+ label,
629
+ data
630
+ }, transferList);
631
+ }
632
+ async request(data, label = null) {
633
+ if (!data) return;
634
+ this.port.postMessage({
635
+ tag: "message",
636
+ label,
637
+ data
638
+ });
639
+ return new Promise((res, rej) => {
640
+ const handler = (data2, label2) => {
641
+ if (label == label2) {
642
+ res(data2);
643
+ this.off("message", handler);
644
+ }
645
+ };
646
+ this.on("message", handler);
647
+ if (this.config.timeout) setTimeout(() => {
648
+ rej(new Error("failed to receive response"));
649
+ this.off("message", handler);
650
+ }, this.config.timeout);
651
+ });
652
+ }
653
+ listenOnce(cb, label = null) {
654
+ const handler = (data, label2) => {
655
+ if (label == label2) {
656
+ cb(data);
657
+ this.off("message", handler);
658
+ }
659
+ };
660
+ this.on("message", handler);
661
+ }
662
+ listenAll(cb, label = null) {
663
+ this.on("message", (data, label2) => {
664
+ if (label == label2) {
665
+ cb(data);
666
+ }
667
+ });
668
+ }
669
+ respondOnce(cb, label = null) {
670
+ const handler = (data, label2) => {
671
+ if (label == label2) {
672
+ this.send(cb(data), label);
673
+ this.off("message", handler);
674
+ }
675
+ };
676
+ this.on("message", handler);
677
+ }
678
+ respondAll(cb, label = null) {
679
+ this.on("message", (data, label2) => {
680
+ if (label == label2) {
681
+ this.send(cb(data), label);
682
+ }
683
+ });
684
+ }
685
+ async addHeap(heap, name) {
686
+ if (heap instanceof SharedArrayBuffer) {
687
+ heap = new SharedHeap(heap);
688
+ }
689
+ const buffer = heap.buffer;
690
+ this.port.postMessage({
691
+ tag: "sync",
692
+ name,
693
+ buffer,
694
+ heapID: heap.heapID,
695
+ rebound: false
696
+ });
697
+ return new Promise((res, rej) => {
698
+ const handler = (name2, buffer2, heapID, rebound) => {
699
+ if (rebound && name == name2 && buffer2 == null && heapID == heap.heapID) {
700
+ res();
701
+ this.off("sync", handler);
702
+ }
703
+ };
704
+ this.on("sync", handler);
705
+ if (this.config.timeout) setTimeout(() => {
706
+ rej(new Error("failed to receive response"));
707
+ this.off("sync", handler);
708
+ }, this.config.timeout);
709
+ });
710
+ }
711
+ async syncHeap(name) {
712
+ return new Promise((res, rej) => {
713
+ const handler = (name2, buffer, heapID, rebound) => {
714
+ if (!rebound && name == name2) {
715
+ const heap = new SharedHeap(buffer, heapID);
716
+ this.port.postMessage({
717
+ tag: "sync",
718
+ name,
719
+ buffer: null,
720
+ heapID: heap.heapID,
721
+ rebound: true
722
+ });
723
+ this.off("sync", handler);
724
+ res(heap);
725
+ }
726
+ };
727
+ this.on("sync", handler);
728
+ if (this.config.timeout) setTimeout(() => {
729
+ rej(new Error("failed to receive response"));
730
+ this.off("sync", handler);
731
+ }, this.config.timeout);
732
+ });
733
+ }
734
+ async addVar(data, name) {
735
+ let heapID = data.heap.heapID;
736
+ let addr = data.addr;
737
+ this.port.postMessage({
738
+ tag: "assign",
739
+ name,
740
+ heapID,
741
+ addr,
742
+ rebound: false
743
+ });
744
+ return new Promise((res, rej) => {
745
+ const handler = (name2, heapID2, addr2, rebound) => {
746
+ if (rebound && name2 == name && heapID2 == heapID && addr2 == addr) {
747
+ this.off("assign", handler);
748
+ res();
749
+ }
750
+ };
751
+ this.on("assign", handler);
752
+ if (this.config.timeout) setTimeout(() => {
753
+ rej(new Error("failed to receive response"));
754
+ this.off("assign", handler);
755
+ }, this.config.timeout);
756
+ });
757
+ }
758
+ async syncVar(name) {
759
+ return new Promise((res, rej) => {
760
+ const handler = (name2, heapID, addr, rebound) => {
761
+ if (!rebound && name2 == name) {
762
+ let heap = SharedHeap.getHeapByID(heapID);
763
+ let isArr = heap.getArrayAt(addr);
764
+ let isPtr = heap.getPtrAt(addr);
765
+ let dataType = TypeRegistry.getTypeByIndex(heap.getTypeIDAt(addr));
766
+ let data;
767
+ if (isArr) {
768
+ data = new SharedArray(heap, addr);
769
+ } else if (isPtr) {
770
+ data = new SharedPointer(heap, addr);
771
+ } else {
772
+ data = new dataType(heap, addr);
773
+ }
774
+ this.port.postMessage({
775
+ tag: "assign",
776
+ name,
777
+ heapID,
778
+ addr,
779
+ rebound: true
780
+ });
781
+ res(data);
782
+ this.off("assign", handler);
783
+ }
784
+ };
785
+ this.on("assign", handler);
786
+ if (this.config.timeout) setTimeout(() => {
787
+ rej(new Error("failed to receive response"));
788
+ this.off("assign", handler);
789
+ }, this.config.timeout);
790
+ });
791
+ }
792
+ };
793
+
794
+ // src/Threads/MainThread.ts
795
+ import os from "os";
796
+ var MainThread = class extends Thread {
797
+ static get optimalTypeRegistrys() {
798
+ return os.availableParallelism();
799
+ }
800
+ worker;
801
+ active = false;
802
+ constructor(path, config = {}) {
803
+ config = { ...config };
804
+ config.workerOptions ??= {};
805
+ config.workerOptions.transferList ??= [];
806
+ config.workerOptions.workerData = {
807
+ config: {
808
+ timeout: config.timeout,
809
+ logLevel: config.logLevel
810
+ },
811
+ default: config.workerOptions.workerData
812
+ };
813
+ if (config.useTypescript) {
814
+ if (config.workerOptions.execArgv) {
815
+ config.workerOptions.execArgv.push("--import");
816
+ config.workerOptions.execArgv.push("tsx");
817
+ } else {
818
+ config.workerOptions.execArgv = [...process.execArgv, "--import", "tsx"];
819
+ }
820
+ }
821
+ let typeBuffer = TypeRegistry.getTypeBuffer();
822
+ config.workerOptions.transferList.push(typeBuffer);
823
+ config.workerOptions.workerData = {
824
+ orig: config.workerOptions.workerData,
825
+ //extra data here for syncing
826
+ types: typeBuffer
827
+ };
828
+ if (path instanceof Function) {
829
+ path = path.toString();
830
+ config.workerOptions.eval = true;
831
+ }
832
+ let worker = new Worker(path, config.workerOptions);
833
+ let port = worker;
834
+ super(port, config);
835
+ this.worker = worker;
836
+ this.port.on("message", (msg) => {
837
+ this.emit("internalmessage", msg);
838
+ switch (msg.tag) {
839
+ case "message":
840
+ this.emit("message", msg.data, msg.label);
841
+ break;
842
+ case "sync":
843
+ this.emit("sync", msg.name, msg.buffer, msg.heapID, msg.rebound);
844
+ break;
845
+ case "assign":
846
+ this.emit("assign", msg.name, msg.heapID, msg.addr, msg.rebound);
847
+ break;
848
+ }
849
+ if (this.config.transient) {
850
+ this.worker.terminate();
851
+ }
852
+ });
853
+ this.worker.on("error", (err) => {
854
+ let caught = this.emit("error", err);
855
+ if (!caught) {
856
+ this.err(err);
857
+ }
858
+ });
859
+ this.port.on("messageerror", (err) => {
860
+ let caught = this.emit("messageerror", err);
861
+ if (!caught) {
862
+ this.err(err);
863
+ }
864
+ });
865
+ this.worker.on("online", () => {
866
+ this.emit("online");
867
+ this.active = true;
868
+ });
869
+ this.worker.on("exit", (exitCode) => {
870
+ this.active = false;
871
+ this.emit("exit", exitCode);
872
+ });
873
+ }
874
+ async ready() {
875
+ if (this.active) return;
876
+ return new Promise((res) => {
877
+ this.port.once("online", () => {
878
+ res();
879
+ });
880
+ });
881
+ }
882
+ terminate() {
883
+ if (!this.active) this.err("cannot terminate worker(worker is not active)");
884
+ this.active = false;
885
+ return this.worker.terminate();
886
+ }
887
+ // private log(level: number, msg: string): void{
888
+ // ///////TODO
889
+ // if(level >= (this.config.logLevel ?? 0)){
890
+ // console.log(`${new Date().toTimeString()} - ${threadName}(${threadId}) - ${msg}`);
891
+ // }
892
+ // }
893
+ err(msg) {
894
+ throw new Error(`${(/* @__PURE__ */ new Date()).toTimeString()} - ${threadName}(${threadId}) - ${msg}`);
895
+ }
896
+ get isActive() {
897
+ return this.active;
898
+ }
899
+ //functions that pass through the call
900
+ ref() {
901
+ this.port.ref();
902
+ }
903
+ unref() {
904
+ this.port.unref();
905
+ }
906
+ //todo
907
+ // worker.cpuUsage([prev])
908
+ // worker.getHeapSnapshot([options])
909
+ // worker.getHeapStatistics()
910
+ // worker.performance
911
+ // worker.stderr
912
+ // worker.stdin
913
+ // worker.stdout
914
+ };
915
+
916
+ // src/Threads/WorkerThread.ts
917
+ import { parentPort, threadName as threadName2, threadId as threadId2, workerData } from "worker_threads";
918
+ var WorkerThread = class extends Thread {
919
+ _workerData = workerData.workerData;
920
+ constructor() {
921
+ if (parentPort == null) throw new Error("cannot find parent port");
922
+ super(parentPort, workerData.config);
923
+ this._workerData = workerData.default;
924
+ queueMicrotask(() => {
925
+ TypeRegistry.verifyTypeBuffer(workerData.types);
926
+ });
927
+ this.port.on("message", (msg) => {
928
+ this.emit("internalmessage", msg);
929
+ switch (msg.tag) {
930
+ case "message":
931
+ this.emit("message", msg.data, msg.label);
932
+ break;
933
+ case "sync":
934
+ this.emit("sync", msg.name, msg.buffer, msg.heapID, msg.rebound);
935
+ break;
936
+ case "assign":
937
+ this.emit("assign", msg.name, msg.heapID, msg.addr, msg.rebound);
938
+ break;
939
+ }
940
+ });
941
+ this.port.on("messageerror", (err) => {
942
+ let caught = this.emit("messageerror", err);
943
+ if (!caught) {
944
+ this.err(err);
945
+ }
946
+ });
947
+ }
948
+ get workerData() {
949
+ return this._workerData;
950
+ }
951
+ err(msg) {
952
+ throw new Error(`${(/* @__PURE__ */ new Date()).toTimeString()} - ${threadName2}(${threadId2}) - ${msg}`);
953
+ }
954
+ };
955
+
956
+ // src/Threads/index.ts
957
+ import { isMainThread } from "worker_threads";
958
+ var WorkerThreadExport = isMainThread ? WorkerThread : new WorkerThread();
959
+ export {
960
+ Int32,
961
+ MainThread,
962
+ SharedArray,
963
+ SharedHeap,
964
+ SharedInt32,
965
+ SharedPointer,
966
+ SharedPrimitive,
967
+ SharedReference,
968
+ SharedStruct,
969
+ SharedType,
970
+ SharedUint32,
971
+ Thread,
972
+ TypeRegistry,
973
+ Uint32,
974
+ WorkerThreadExport as WorkerThread,
975
+ isMainThread2 as isMainThread
976
+ };