@daneren2005/shared-memory-objects 0.0.10 → 0.0.11

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.
Files changed (44) hide show
  1. package/dist/shared-memory-objects.js +1325 -0
  2. package/dist/shared-memory-objects.umd.cjs +1 -0
  3. package/dist/src/allocated-memory.d.ts +26 -0
  4. package/dist/src/cached-item-list.d.ts +37 -0
  5. package/{src/interfaces/pow2.ts → dist/src/interfaces/pow2.d.ts} +2 -3
  6. package/dist/src/interfaces/typed-array-constructor.d.ts +5 -0
  7. package/{src/interfaces/typed-array.ts → dist/src/interfaces/typed-array.d.ts} +1 -1
  8. package/dist/src/lock/read-write-lock.d.ts +5 -0
  9. package/dist/src/lock/simple-lock.d.ts +3 -0
  10. package/dist/src/main.d.ts +18 -0
  11. package/dist/src/memory-buffer.d.ts +185 -0
  12. package/dist/src/memory-heap.d.ts +34 -0
  13. package/dist/src/serialize-object.d.ts +5 -0
  14. package/dist/src/shared-list.d.ts +44 -0
  15. package/dist/src/shared-map.d.ts +25 -0
  16. package/dist/src/shared-pointer-list.d.ts +21 -0
  17. package/dist/src/shared-string.d.ts +23 -0
  18. package/dist/src/shared-vector.d.ts +40 -0
  19. package/dist/src/utils/16-from-32-array.d.ts +4 -0
  20. package/dist/src/utils/16-from-64-array.d.ts +2 -0
  21. package/dist/src/utils/float32-atomics.d.ts +5 -0
  22. package/dist/src/utils/pointer.d.ts +19 -0
  23. package/package.json +17 -5
  24. package/src/allocated-memory.ts +0 -89
  25. package/src/cached-item-list.ts +0 -143
  26. package/src/interfaces/typed-array-constructor.ts +0 -6
  27. package/src/lock/read-write-lock.ts +0 -41
  28. package/src/lock/simple-lock.ts +0 -21
  29. package/src/main.ts +0 -40
  30. package/src/memory-buffer.ts +0 -666
  31. package/src/memory-heap.ts +0 -206
  32. package/src/serialize-object.ts +0 -95
  33. package/src/shared-list.ts +0 -339
  34. package/src/shared-map.ts +0 -252
  35. package/src/shared-pointer-list.ts +0 -80
  36. package/src/shared-string.ts +0 -144
  37. package/src/shared-vector.ts +0 -236
  38. package/src/utils/16-from-32-array.ts +0 -23
  39. package/src/utils/16-from-64-array.ts +0 -18
  40. package/src/utils/float32-atomics.ts +0 -26
  41. package/src/utils/pointer.ts +0 -40
  42. package/src/utils/typedarray.js +0 -162
  43. package/src/vite-env.d.ts +0 -1
  44. /package/{src → dist/src}/utils/typedarray.d.ts +0 -0
package/src/shared-map.ts DELETED
@@ -1,252 +0,0 @@
1
- import AllocatedMemory, { type SharedAllocatedMemory } from './allocated-memory';
2
- import type MemoryHeap from './memory-heap';
3
- import SharedList from './shared-list';
4
- import { loadPointer, storePointer } from './utils/pointer';
5
-
6
- // TODO: Grow hashMemory
7
- // TODO: Add iterator
8
- // TODO: Add read/write locks
9
- const DEFAULT_HASH_SIZE = 10;
10
- export default class SharedMap<K extends string | number> {
11
- static readonly ALLOCATE_COUNT = 4;
12
-
13
- private memory: MemoryHeap;
14
- // Memory order: Pointer, Lock, Length, MaxHash
15
- private pointerMemory: AllocatedMemory;
16
- private lock: Int32Array;
17
- private get hashMemory(): AllocatedMemory {
18
- return new AllocatedMemory(this.memory, loadPointer(this.pointerMemory.data, 0));
19
- }
20
-
21
- get length(): number {
22
- return Atomics.load(this.pointerMemory.data, 2);
23
- }
24
- get maxHash(): number {
25
- return Atomics.load(this.pointerMemory.data, 3);
26
- }
27
-
28
- constructor(memory: MemoryHeap, clone?: SharedMapMemory) {
29
- this.memory = memory;
30
-
31
- if(clone) {
32
- this.pointerMemory = new AllocatedMemory(memory, clone.firstBlock);
33
- } else {
34
- this.pointerMemory = memory.allocUI32(SharedMap.ALLOCATE_COUNT);
35
- let hashMemory = memory.allocUI32(DEFAULT_HASH_SIZE);
36
- storePointer(this.pointerMemory.data, 0, hashMemory.bufferPosition, hashMemory.bufferByteOffset);
37
- Atomics.store(this.pointerMemory.data, 3, DEFAULT_HASH_SIZE);
38
- }
39
- this.lock = new Int32Array(this.pointerMemory.data.buffer, this.pointerMemory.bufferByteOffset + Uint32Array.BYTES_PER_ELEMENT, 1);
40
- }
41
-
42
- set(key: K, value: number) {
43
- if(this.length >= this.maxHash * 2) {
44
- this.growHashTable();
45
- }
46
-
47
- let fullHashKey = get32BitHash(key);
48
- if(this.setHashKey(this.hashMemory, this.maxHash, fullHashKey, value)) {
49
- Atomics.add(this.pointerMemory.data, 2, 1);
50
- }
51
- }
52
- private setHashKey(hashMemory: AllocatedMemory, maxHash: number, fullHashKey: number, value: number) {
53
- let hashKey = this.hash(fullHashKey, maxHash);
54
-
55
- let list: SharedList;
56
- let pointer = loadPointer(hashMemory.data, hashKey);
57
- if(pointer.bufferByteOffset === 0) {
58
- // Initialize a list here
59
- list = new SharedList(this.memory, {
60
- dataLength: 2
61
- });
62
-
63
- let listMemory = list.getSharedMemory();
64
- storePointer(hashMemory.data, hashKey, listMemory.firstBlock.bufferPosition, listMemory.firstBlock.bufferByteOffset);
65
- } else {
66
- list = new SharedList(this.memory, {
67
- firstBlock: pointer
68
- });
69
- }
70
-
71
- // Check if any other items in list have the same key and delete them
72
- let inserted = true;
73
- if(list.deleteValue(fullHashKey)) {
74
- inserted = false;
75
- }
76
- list.insert([fullHashKey, value]);
77
-
78
- return inserted;
79
- }
80
-
81
- get(key: K): number | undefined {
82
- let fullHashKey = get32BitHash(key);
83
- let hashKey = this.hash(fullHashKey, this.maxHash);
84
-
85
- let pointer = loadPointer(this.hashMemory.data, hashKey);
86
- if(pointer.bufferByteOffset === 0) {
87
- return undefined;
88
- }
89
-
90
- let list = new SharedList(this.memory, {
91
- firstBlock: pointer
92
- });
93
-
94
- for(let { data } of list) {
95
- if(data[0] === fullHashKey) {
96
- return data[1];
97
- }
98
- }
99
-
100
- return undefined;
101
- }
102
- has(key: K): boolean {
103
- let fullHashKey = get32BitHash(key);
104
- let hashKey = this.hash(fullHashKey, this.maxHash);
105
-
106
- let pointer = loadPointer(this.hashMemory.data, hashKey);
107
- if(pointer.bufferByteOffset === 0) {
108
- return false;
109
- }
110
-
111
- let list = new SharedList(this.memory, {
112
- firstBlock: pointer
113
- });
114
-
115
- for(let { data } of list) {
116
- if(data[0] === fullHashKey) {
117
- return true;
118
- }
119
- }
120
-
121
- return false;
122
- }
123
-
124
- delete(key: K): boolean {
125
- let fullHashKey = get32BitHash(key);
126
- let hashKey = this.hash(fullHashKey, this.maxHash);
127
-
128
- let pointer = loadPointer(this.hashMemory.data, hashKey);
129
- if(pointer.bufferByteOffset === 0) {
130
- return false;
131
- }
132
-
133
- let list = new SharedList(this.memory, {
134
- firstBlock: pointer
135
- });
136
-
137
- for(let { data, deleteCurrent } of list) {
138
- if(data[0] === fullHashKey) {
139
- deleteCurrent();
140
-
141
- Atomics.sub(this.pointerMemory.data, 2, 1);
142
- return true;
143
- }
144
- }
145
-
146
- return false;
147
- }
148
-
149
- private growHashTable() {
150
- let oldMaxHash = this.maxHash;
151
- let newMaxHash = oldMaxHash * 2;
152
- let newHashMemory = this.memory.allocUI32(newMaxHash);
153
- let oldHashMemory = this.hashMemory;
154
-
155
- // Copy each old hash value into new hash memory
156
- for(let i = 0; i < oldMaxHash; i++) {
157
- let pointer = loadPointer(oldHashMemory.data, i);
158
- if(pointer.bufferByteOffset === 0) {
159
- continue;
160
- }
161
-
162
- let list = new SharedList(this.memory, {
163
- firstBlock: pointer
164
- });
165
- for(let { data } of list) {
166
- this.setHashKey(newHashMemory, newMaxHash, data[0], data[1]);
167
- }
168
- }
169
-
170
- storePointer(this.pointerMemory.data, 0, newHashMemory.bufferPosition, newHashMemory.bufferByteOffset);
171
- Atomics.store(this.pointerMemory.data, 3, newMaxHash);
172
- }
173
-
174
- private hash(key: number, maxHash: number) {
175
- return key % maxHash;
176
- }
177
-
178
- free() {
179
- // Loop through and free lists in hash table first
180
- for(let i = 0; i < this.maxHash; i++) {
181
- let pointer = loadPointer(this.hashMemory.data, i);
182
- if(pointer.bufferByteOffset === 0) {
183
- continue;
184
- }
185
-
186
- let list = new SharedList(this.memory, {
187
- firstBlock: pointer
188
- });
189
- list.free();
190
- }
191
-
192
- this.hashMemory.free();
193
- this.pointerMemory.free();
194
- }
195
-
196
- getSharedMemory(): SharedMapMemory {
197
- return {
198
- firstBlock: this.pointerMemory.getSharedMemory()
199
- };
200
- }
201
- }
202
-
203
- interface SharedMapMemory {
204
- firstBlock: SharedAllocatedMemory
205
- }
206
-
207
- function get32BitHash<K extends string | number>(key: K): number {
208
- if(typeof key === 'number') {
209
- return key;
210
- } else if(typeof key === 'string') {
211
- return hashString(key as string);
212
- } else {
213
- return key;
214
- }
215
- }
216
-
217
- // Copied from https://github.com/mmomtchev/SharedMap/blob/master/index.js - MurmurHash2
218
- function hashString(str: string): number {
219
- let
220
- l = str.length,
221
- h = 17 ^ l,
222
- i = 0,
223
- k;
224
- while(l >= 4) {
225
- k =
226
- ((str.charCodeAt(i) & 0xff)) |
227
- ((str.charCodeAt(++i) & 0xff) << 8) |
228
- ((str.charCodeAt(++i) & 0xff) << 16) |
229
- ((str.charCodeAt(++i) & 0xff) << 14);
230
- k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
231
- k ^= k >>> 14;
232
- k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
233
- h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;
234
- l -= 4;
235
- ++i;
236
- }
237
- /* eslint-disable no-fallthrough */
238
- switch(l) {
239
- case 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
240
- case 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
241
- case 1: h ^= (str.charCodeAt(i) & 0xff);
242
- h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
243
- }
244
- /* eslint-enable no-fallthrough */
245
- h ^= h >>> 13;
246
- h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
247
- h ^= h >>> 15;
248
- h = h >>> 0;
249
- return h;
250
- }
251
-
252
- export type { SharedMapMemory };
@@ -1,80 +0,0 @@
1
- import AllocatedMemory from './allocated-memory';
2
- import type MemoryHeap from './memory-heap';
3
- import type { SharedListMemory } from './shared-list';
4
- import SharedList from './shared-list';
5
- import { createPointer, loadPointer } from './utils/pointer';
6
-
7
- export default abstract class SharedPointerList<T extends PointerItem> implements Iterable<T> {
8
- private memory: MemoryHeap;
9
- private list: SharedList;
10
-
11
- constructor(heap: MemoryHeap, memory?: SharedListMemory) {
12
- this.memory = heap;
13
-
14
- if(memory) {
15
- this.list = new SharedList(heap, memory);
16
- } else {
17
- this.list = new SharedList(heap);
18
- }
19
- }
20
-
21
- get length() {
22
- return this.list.length;
23
- }
24
-
25
- insert(item: T) {
26
- this.list.insert(createPointer(item.memory.bufferPosition, item.memory.bufferByteOffset));
27
- }
28
- delete(item: T) {
29
- return this.list.deleteValue(createPointer(item.memory.bufferPosition, item.memory.bufferByteOffset));
30
- }
31
-
32
- *[Symbol.iterator]() {
33
- let iterator = this.list[Symbol.iterator]();
34
-
35
- for(let { data: pointerData } of iterator) {
36
- let { bufferPosition, bufferByteOffset } = loadPointer(pointerData, 0);
37
- let allocatedMemory = new AllocatedMemory(this.memory, {
38
- bufferPosition,
39
- bufferByteOffset
40
- });
41
- yield this.createItem(allocatedMemory);
42
- }
43
- }
44
- forEach(callback: (item: T) => void) {
45
- for(let value of this) {
46
- callback(value);
47
- }
48
- }
49
-
50
- find(callback: (item: T) => boolean): T | undefined {
51
- for(let value of this) {
52
- if(callback(value)) {
53
- return value;
54
- }
55
- }
56
- }
57
-
58
- getSharedMemory() {
59
- return this.list.getSharedMemory();
60
- }
61
-
62
- protected abstract createItem(allocatedMemory: AllocatedMemory): T;
63
-
64
- free() {
65
- for(let item of this) {
66
- // NOTE: Anything that allocates it's own memory (ie: type for Item) needs to call free for that class so we can clear all memory recursively
67
- if('free' in item && typeof item.free === 'function') {
68
- item.free();
69
- } else {
70
- item.memory.free();
71
- }
72
- }
73
-
74
- this.list.free();
75
- }
76
- }
77
-
78
- interface PointerItem {
79
- readonly memory: AllocatedMemory
80
- }
@@ -1,144 +0,0 @@
1
- import AllocatedMemory from './allocated-memory';
2
- import type { SharedAllocatedMemory } from './allocated-memory';
3
- import { lock, unlock } from './lock/simple-lock';
4
- import type MemoryHeap from './memory-heap';
5
- import { getPointer, loadPointer, loadRawPointer, storeRawPointer } from './utils/pointer';
6
-
7
- enum CHAR_TYPE {
8
- UNDEFINED,
9
- ASCII,
10
- UTF16
11
- }
12
- const TYPED_ARRAY_MAP = {
13
- [CHAR_TYPE.ASCII]: Uint8Array,
14
- [CHAR_TYPE.UTF16]: Uint16Array
15
- };
16
-
17
- const POINTER_INDEX = 0;
18
- const LENGTH_INDEX = 1;
19
- const TYPE_INDEX = 2;
20
- const LOCK_INDEX = 3;
21
- export default class SharedString {
22
- static readonly ALLOCATE_COUNT = 4;
23
-
24
- private memory: MemoryHeap;
25
- private allocatedMemory: AllocatedMemory;
26
- private lock: Int32Array;
27
-
28
- private cachedPointer?: number;
29
- private cachedString?: string;
30
-
31
- constructor(memory: MemoryHeap, value: string | SharedStringConfig | SharedStringMemory) {
32
- this.memory = memory;
33
-
34
- if(typeof value === 'string') {
35
- this.allocatedMemory = this.memory.allocUI32(SharedString.ALLOCATE_COUNT);
36
- this.lock = new Int32Array(this.allocatedMemory.data.buffer, this.allocatedMemory.bufferByteOffset + LOCK_INDEX * this.allocatedMemory.data.BYTES_PER_ELEMENT);
37
- this.updateString(value);
38
- } else {
39
- this.allocatedMemory = new AllocatedMemory(memory, value);
40
- this.lock = new Int32Array(this.allocatedMemory.data.buffer, this.allocatedMemory.bufferByteOffset + LOCK_INDEX * this.allocatedMemory.data.BYTES_PER_ELEMENT);
41
-
42
- // We only allocated memory but didn't initialize the string yet
43
- if('value' in value) {
44
- this.updateString(value.value);
45
- }
46
- }
47
- }
48
-
49
- private updateString(value: string) {
50
- let stringMemory = this.createString(value);
51
-
52
- lock(this.lock);
53
- storeRawPointer(this.allocatedMemory.data, POINTER_INDEX, stringMemory.pointer);
54
- Atomics.store(this.allocatedMemory.data, LENGTH_INDEX, value.length);
55
- Atomics.store(this.allocatedMemory.data, TYPE_INDEX, stringMemory.charType);
56
- unlock(this.lock);
57
-
58
- this.cachedPointer = stringMemory.pointer;
59
- this.cachedString = value;
60
- }
61
- private createString(value: string) {
62
- if(value === '') {
63
- return {
64
- pointer: 0,
65
- charType: CHAR_TYPE.ASCII
66
- };
67
- }
68
-
69
- let charCodes = [];
70
- for(let i = 0; i < value.length; i++) {
71
- charCodes.push(value.charCodeAt(i));
72
- }
73
-
74
- let maxCharCode = Math.max(...charCodes);
75
- let charType = maxCharCode > 255 ? CHAR_TYPE.UTF16 : CHAR_TYPE.ASCII;
76
-
77
- let typedArray = TYPED_ARRAY_MAP[charType];
78
- let allocatedMemory = this.memory.allocUI32(Math.ceil(value.length / (4 / typedArray.BYTES_PER_ELEMENT)));
79
- let data = new typedArray(allocatedMemory.data.buffer, allocatedMemory.data.byteOffset, value.length);
80
- for(let i = 0; i < value.length; i++) {
81
- data[i] = value.charCodeAt(i);
82
- }
83
-
84
- return {
85
- pointer: allocatedMemory.pointer,
86
- charType
87
- };
88
- }
89
-
90
- get value(): string {
91
- let pointer = loadRawPointer(this.allocatedMemory.data, POINTER_INDEX);
92
- if(this.cachedPointer === pointer && this.cachedString !== undefined) {
93
- return this.cachedString;
94
- } else if(pointer === 0) {
95
- return '';
96
- }
97
- let { bufferPosition, bufferByteOffset } = getPointer(pointer);
98
-
99
- lock(this.lock);
100
- let charType = Atomics.load(this.allocatedMemory.data, TYPE_INDEX) as number;
101
- // @ts-expect-error
102
- let typedArray = TYPED_ARRAY_MAP[charType];
103
- let bufferLength = Atomics.load(this.allocatedMemory.data, LENGTH_INDEX);
104
-
105
- let data = new typedArray(this.memory.buffers[bufferPosition].buf, bufferByteOffset, bufferLength);
106
- let string = String.fromCharCode.apply(null, data);
107
- // NOTE: Do not unlock until after transforming the data since the second this is done it can free that memory block
108
- unlock(this.lock);
109
-
110
- this.cachedPointer = pointer;
111
- this.cachedString = string;
112
-
113
- return string;
114
- }
115
- set value(value: string) {
116
- let { bufferPosition: oldBufferPosition, bufferByteOffset: oldBufferByteOffset } = loadPointer(this.allocatedMemory.data, POINTER_INDEX);
117
- this.updateString(value);
118
-
119
- if(oldBufferByteOffset) {
120
- this.memory.buffers[oldBufferPosition].free(oldBufferByteOffset);
121
- }
122
- }
123
-
124
- getSharedMemory(): SharedStringMemory {
125
- return this.allocatedMemory.getSharedMemory();
126
- }
127
-
128
- get pointer() {
129
- return this.allocatedMemory.pointer;
130
- }
131
-
132
- free() {
133
- let { bufferPosition, bufferByteOffset } = loadPointer(this.allocatedMemory.data, POINTER_INDEX);
134
- if(bufferByteOffset) {
135
- this.memory.buffers[bufferPosition].free(bufferByteOffset);
136
- }
137
- this.allocatedMemory.free();
138
- }
139
- }
140
-
141
- interface SharedStringConfig extends SharedStringMemory {
142
- value: string
143
- }
144
- type SharedStringMemory = SharedAllocatedMemory;
@@ -1,236 +0,0 @@
1
- import type { SharedAllocatedMemory } from './allocated-memory';
2
- import AllocatedMemory from './allocated-memory';
3
- import type { TypedArrayConstructor } from './interfaces/typed-array-constructor';
4
- import type MemoryHeap from './memory-heap';
5
- import { getPointer, loadPointer, storePointer } from './utils/pointer';
6
-
7
- enum TYPE {
8
- uint32,
9
- int32,
10
- float32
11
- }
12
-
13
- const LIST_LENGTH_INDEX = 1;
14
- const BUFFER_LENGTH_INDEX = 2;
15
- const TYPE_INDEX = 3;
16
- const DEFAULT_SIZE = 4;
17
- export default class SharedVector<T extends Uint32Array | Int32Array | Float32Array = Uint32Array> implements Iterable<T> {
18
- static readonly ALLOCATE_COUNT = 4;
19
- private memory: MemoryHeap;
20
-
21
- // Pointer, List Length, Buffer Length, Type/DataLength
22
- private firstBlock: AllocatedMemory;
23
- private uint16Array: Uint16Array;
24
-
25
- get length(): number {
26
- return Atomics.load(this.firstBlock.data, LIST_LENGTH_INDEX);
27
- }
28
-
29
- get type(): number {
30
- return this.uint16Array[0];
31
- }
32
- private set type(value: number) {
33
- Atomics.store(this.uint16Array, 0, value);
34
- }
35
- get dataLength(): number {
36
- // Can technically be initialized by passing memory without actually every being called - need to make sure dataLength is always at least one
37
- return Math.max(1, this.uint16Array[1]);
38
- }
39
- private set dataLength(value: number) {
40
- Atomics.store(this.uint16Array, 1, value);
41
- }
42
-
43
- get bufferLength(): number {
44
- return Atomics.load(this.firstBlock.data, BUFFER_LENGTH_INDEX);
45
- }
46
- private set bufferLength(value: number) {
47
- Atomics.store(this.firstBlock.data, BUFFER_LENGTH_INDEX, value);
48
- }
49
-
50
- private cachedFullDataBlock?: T;
51
- private cachedPointer: number;
52
-
53
- constructor(memory: MemoryHeap, config?: SharedVectorConfig<T> | SharedVectorMemory) {
54
- this.memory = memory;
55
-
56
- if(config && 'firstBlock' in config) {
57
- this.firstBlock = new AllocatedMemory(memory, config.firstBlock);
58
- this.uint16Array = new Uint16Array(this.firstBlock.data.buffer, this.firstBlock.bufferByteOffset + TYPE_INDEX * Uint32Array.BYTES_PER_ELEMENT, 2);
59
- } else {
60
- this.firstBlock = memory.allocUI32(SharedVector.ALLOCATE_COUNT);
61
- this.uint16Array = new Uint16Array(this.firstBlock.data.buffer, this.firstBlock.bufferByteOffset + TYPE_INDEX * Uint32Array.BYTES_PER_ELEMENT, 2);
62
-
63
- let dataLength = config?.dataLength ?? 1;
64
- let bufferLength = config?.bufferLength ?? DEFAULT_SIZE;
65
- let dataBlock = memory.allocUI32(bufferLength * dataLength);
66
- storePointer(this.firstBlock.data, 0, dataBlock.bufferPosition, dataBlock.bufferByteOffset);
67
- this.bufferLength = bufferLength;
68
-
69
- const type = config?.type ?? Uint32Array;
70
- if(type === Uint32Array) {
71
- this.type = TYPE.uint32;
72
- }
73
- // @ts-expect-error
74
- else if(type === Int32Array) {
75
- this.type = TYPE.int32;
76
- }
77
- // @ts-expect-error
78
- else if(type === Float32Array) {
79
- this.type = TYPE.float32;
80
- }
81
- this.dataLength = dataLength;
82
- }
83
-
84
- this.cachedPointer = this.firstBlock.data[0];
85
- this.cachedFullDataBlock = this.getFullDataBlock(this.dataLength);
86
- }
87
-
88
- push(values: number | Array<number>) {
89
- if(typeof values === 'number') {
90
- values = [values];
91
- }
92
-
93
- let dataLength = this.dataLength;
94
- if(values.length > dataLength) {
95
- throw new Error(`Can't insert ${values.length} array into shared list of ${dataLength} dataLength`);
96
- }
97
-
98
- let dataBlock = this.getFullDataBlock(dataLength);
99
- let currentLength = this.length;
100
- dataBlock.set(values, dataLength * currentLength);
101
-
102
- let newLength = Atomics.add(this.firstBlock.data, LIST_LENGTH_INDEX, LIST_LENGTH_INDEX) + 1;
103
- if(newLength >= this.bufferLength) {
104
- this.growBuffer();
105
- }
106
- }
107
-
108
- pop(): T {
109
- let oldLength = Atomics.sub(this.firstBlock.data, LIST_LENGTH_INDEX, LIST_LENGTH_INDEX);
110
-
111
- let pointer = loadPointer(this.firstBlock.data, 0);
112
- let dataMemory = new AllocatedMemory(this.memory, pointer);
113
- return this.getDataBlock(dataMemory.data, oldLength - 1);
114
- }
115
-
116
- deleteIndex(index: number) {
117
- let length = this.length;
118
- if(index >= length || index < 0) {
119
- throw new Error(`${index} is out of bounds ${length}`);
120
- }
121
-
122
- let dataLength = this.dataLength;
123
- let dataBlock = this.getFullDataBlock(dataLength);
124
- for(let i = index; i < length; i++) {
125
- for(let j = 0; j < dataLength; j++) {
126
- dataBlock[i * dataLength + j] = dataBlock[(i + 1) * dataLength + j];
127
- }
128
- }
129
-
130
- Atomics.sub(this.firstBlock.data, LIST_LENGTH_INDEX, LIST_LENGTH_INDEX);
131
- }
132
-
133
- clear() {
134
- this.firstBlock.data[LIST_LENGTH_INDEX] = 0;
135
- }
136
-
137
- *[Symbol.iterator]() {
138
- let pointer = loadPointer(this.firstBlock.data, 0);
139
- let dataMemory = new AllocatedMemory(this.memory, pointer);
140
-
141
- for(let i = 0; i < this.length; i++) {
142
- yield this.getDataBlock(dataMemory.data, i);
143
- }
144
- }
145
-
146
- private getFullDataBlock(dataLength: number): T {
147
- let pointerNumber = Atomics.load(this.firstBlock.data, 0);
148
- if(this.cachedPointer === pointerNumber && this.cachedFullDataBlock) {
149
- return this.cachedFullDataBlock;
150
- }
151
-
152
- let pointer = getPointer(pointerNumber);
153
- let rawData = new AllocatedMemory(this.memory, pointer);
154
-
155
- let data: T;
156
- switch(this.type) {
157
- case TYPE.int32:
158
- // @ts-expect-error
159
- data = new Int32Array(rawData.data.buffer, rawData.bufferByteOffset, dataLength * this.bufferLength);
160
- break;
161
- case TYPE.uint32:
162
- // @ts-expect-error
163
- data = new Uint32Array(rawData.data.buffer, rawData.bufferByteOffset, dataLength * this.bufferLength);
164
- break;
165
- case TYPE.float32:
166
- // @ts-expect-error
167
- data = new Float32Array(rawData.data.buffer, smemory.bufferByteOffset, dataLength * this.bufferLength);
168
- break;
169
- default:
170
- throw new Error(`Unknown data block type ${this.type}`);
171
- }
172
-
173
- this.cachedPointer = pointerNumber;
174
- this.cachedFullDataBlock = data;
175
-
176
- return data;
177
- }
178
- private getDataBlock(rawData: Uint32Array, index: number): T {
179
- switch(this.type) {
180
- case TYPE.int32:
181
- // @ts-expect-error
182
- return new Int32Array(rawData.buffer, rawData.byteOffset + index * this.dataLength * 4, this.dataLength);
183
- case TYPE.uint32:
184
- // @ts-expect-error
185
- return new Uint32Array(rawData.buffer, rawData.byteOffset + index * this.dataLength * 4, this.dataLength);
186
- case TYPE.float32:
187
- // @ts-expect-error
188
- return new Float32Array(rawData.buffer, smemory.byteOffset + index * this.dataLength * 4, this.dataLength);
189
- default:
190
- throw new Error(`Unknown data block type ${this.type}`);
191
- }
192
- }
193
-
194
- private growBuffer() {
195
- let oldBufferLength = this.bufferLength;
196
- let newBufferLength = oldBufferLength * 2;
197
- let dataLength = this.dataLength;
198
-
199
- let oldPointer = loadPointer(this.firstBlock.data, 0);
200
- let oldDataMemory = new AllocatedMemory(this.memory, oldPointer);
201
- let oldDataBlock = this.getFullDataBlock(dataLength);
202
- let newDataBlock = this.memory.allocUI32(newBufferLength * dataLength);
203
- // Copy old buffer into new buffer
204
- newDataBlock.data.set(oldDataBlock);
205
-
206
- storePointer(this.firstBlock.data, 0, newDataBlock.bufferPosition, newDataBlock.bufferByteOffset);
207
- this.bufferLength = newBufferLength;
208
- oldDataMemory.free();
209
- }
210
-
211
- free() {
212
- let pointer = loadPointer(this.firstBlock.data, 0);
213
- let dataMemory = new AllocatedMemory(this.memory, pointer);
214
-
215
- dataMemory.free();
216
- this.firstBlock.free();
217
- }
218
-
219
- getSharedMemory(): SharedVectorMemory {
220
- return {
221
- firstBlock: this.firstBlock.getSharedMemory()
222
- };
223
- }
224
- }
225
-
226
- interface SharedVectorConfig<T extends Uint32Array | Int32Array | Float32Array> {
227
- type?: TypedArrayConstructor<T>
228
- dataLength?: number
229
-
230
- bufferLength?: number
231
- }
232
- interface SharedVectorMemory {
233
- firstBlock: SharedAllocatedMemory
234
- }
235
-
236
- export type { SharedVectorConfig, SharedVectorMemory };