@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.
- package/dist/shared-memory-objects.js +1325 -0
- package/dist/shared-memory-objects.umd.cjs +1 -0
- package/dist/src/allocated-memory.d.ts +26 -0
- package/dist/src/cached-item-list.d.ts +37 -0
- package/{src/interfaces/pow2.ts → dist/src/interfaces/pow2.d.ts} +2 -3
- package/dist/src/interfaces/typed-array-constructor.d.ts +5 -0
- package/{src/interfaces/typed-array.ts → dist/src/interfaces/typed-array.d.ts} +1 -1
- package/dist/src/lock/read-write-lock.d.ts +5 -0
- package/dist/src/lock/simple-lock.d.ts +3 -0
- package/dist/src/main.d.ts +18 -0
- package/dist/src/memory-buffer.d.ts +185 -0
- package/dist/src/memory-heap.d.ts +34 -0
- package/dist/src/serialize-object.d.ts +5 -0
- package/dist/src/shared-list.d.ts +44 -0
- package/dist/src/shared-map.d.ts +25 -0
- package/dist/src/shared-pointer-list.d.ts +21 -0
- package/dist/src/shared-string.d.ts +23 -0
- package/dist/src/shared-vector.d.ts +40 -0
- package/dist/src/utils/16-from-32-array.d.ts +4 -0
- package/dist/src/utils/16-from-64-array.d.ts +2 -0
- package/dist/src/utils/float32-atomics.d.ts +5 -0
- package/dist/src/utils/pointer.d.ts +19 -0
- package/package.json +17 -5
- package/src/allocated-memory.ts +0 -89
- package/src/cached-item-list.ts +0 -143
- package/src/interfaces/typed-array-constructor.ts +0 -6
- package/src/lock/read-write-lock.ts +0 -41
- package/src/lock/simple-lock.ts +0 -21
- package/src/main.ts +0 -40
- package/src/memory-buffer.ts +0 -666
- package/src/memory-heap.ts +0 -206
- package/src/serialize-object.ts +0 -95
- package/src/shared-list.ts +0 -339
- package/src/shared-map.ts +0 -252
- package/src/shared-pointer-list.ts +0 -80
- package/src/shared-string.ts +0 -144
- package/src/shared-vector.ts +0 -236
- package/src/utils/16-from-32-array.ts +0 -23
- package/src/utils/16-from-64-array.ts +0 -18
- package/src/utils/float32-atomics.ts +0 -26
- package/src/utils/pointer.ts +0 -40
- package/src/utils/typedarray.js +0 -162
- package/src/vite-env.d.ts +0 -1
- /package/{src → dist/src}/utils/typedarray.d.ts +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@daneren2005/shared-memory-objects",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"author": "daneren2005@gmail.com",
|
|
5
5
|
"description": "Creating objects with a SharedArrayBuffer",
|
|
6
6
|
"homepage": "https://github.com/daneren2005/shared-memory-objects#readme",
|
|
@@ -17,14 +17,24 @@
|
|
|
17
17
|
},
|
|
18
18
|
"type": "module",
|
|
19
19
|
"files": [
|
|
20
|
-
"
|
|
21
|
-
"!__tests__"
|
|
20
|
+
"dist/"
|
|
22
21
|
],
|
|
23
|
-
"main": "./
|
|
22
|
+
"main": "./dist/shared-memory-objects.js",
|
|
24
23
|
"exports": {
|
|
25
|
-
".":
|
|
24
|
+
".": {
|
|
25
|
+
"import": {
|
|
26
|
+
"default": "./dist/shared-memory-objects.js",
|
|
27
|
+
"types": "./dist/src/main.d.ts"
|
|
28
|
+
},
|
|
29
|
+
"require": {
|
|
30
|
+
"default": "./dist/shared-memory-objects.js",
|
|
31
|
+
"types": "./dist/src/main.d.ts"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
26
34
|
},
|
|
35
|
+
"types": "./dist/src/main.d.ts",
|
|
27
36
|
"scripts": {
|
|
37
|
+
"build": "vite build",
|
|
28
38
|
"dev": "vite",
|
|
29
39
|
"lint": "eslint src/ --ext .js,.cjs,.mjs,.ts,.cts,.mts --ignore-path .gitignore",
|
|
30
40
|
"preview": "vite preview",
|
|
@@ -38,6 +48,7 @@
|
|
|
38
48
|
"prepare": "husky"
|
|
39
49
|
},
|
|
40
50
|
"devDependencies": {
|
|
51
|
+
"@microsoft/api-extractor": "^7.53.2",
|
|
41
52
|
"@rushstack/eslint-patch": "^1.10.1",
|
|
42
53
|
"@tsconfig/node18": "^18.2.4",
|
|
43
54
|
"@types/jsdom": "^21.1.6",
|
|
@@ -51,6 +62,7 @@
|
|
|
51
62
|
"lint-staged": "^15.2.2",
|
|
52
63
|
"typescript": "^5.4.3",
|
|
53
64
|
"typescript-eslint": "^7.5.0",
|
|
65
|
+
"unplugin-dts": "^1.0.0-beta.0",
|
|
54
66
|
"vite": "^5.2.0",
|
|
55
67
|
"vitest": "^1.4.0"
|
|
56
68
|
},
|
package/src/allocated-memory.ts
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import type { TypedArray } from './interfaces/typed-array';
|
|
2
|
-
import type { TypedArrayConstructor } from './interfaces/typed-array-constructor';
|
|
3
|
-
import type MemoryBuffer from './memory-buffer';
|
|
4
|
-
import type MemoryHeap from './memory-heap';
|
|
5
|
-
import { createPointer } from './utils/pointer';
|
|
6
|
-
|
|
7
|
-
export default class AllocatedMemory {
|
|
8
|
-
private readonly memory: MemoryHeap;
|
|
9
|
-
|
|
10
|
-
readonly bufferPosition: number;
|
|
11
|
-
get bufferByteOffset(): number {
|
|
12
|
-
return this.data.byteOffset;
|
|
13
|
-
}
|
|
14
|
-
get pointer(): number {
|
|
15
|
-
return createPointer(this.bufferPosition, this.bufferByteOffset);
|
|
16
|
-
}
|
|
17
|
-
private buffer: MemoryBuffer;
|
|
18
|
-
data: Uint32Array;
|
|
19
|
-
|
|
20
|
-
constructor(memory: MemoryHeap, config: AllocatedMemoryConfig | SharedAllocatedMemory) {
|
|
21
|
-
this.memory = memory;
|
|
22
|
-
|
|
23
|
-
if('buffer' in config) {
|
|
24
|
-
this.data = config.data;
|
|
25
|
-
this.buffer = config.buffer;
|
|
26
|
-
this.bufferPosition = this.memory.buffers.indexOf(config.buffer);
|
|
27
|
-
} else {
|
|
28
|
-
this.bufferPosition = config.bufferPosition;
|
|
29
|
-
this.buffer = memory.buffers[config.bufferPosition];
|
|
30
|
-
|
|
31
|
-
// Making sure these are the correct size is slow but in dev we want to make sure we aren't allowing to go out of bounds
|
|
32
|
-
if(import.meta.env.MODE === 'production') {
|
|
33
|
-
this.data = new Uint32Array(this.buffer.buf, config.bufferByteOffset);
|
|
34
|
-
} else {
|
|
35
|
-
this.data = new Uint32Array(this.buffer.buf, config.bufferByteOffset, this.buffer.lengthOf(config.bufferByteOffset));
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
getArray<T extends TypedArray>(type: TypedArrayConstructor<T>, offset: number, length: number): T {
|
|
41
|
-
if(import.meta.env.MODE === 'development' || import.meta.env.MODE === 'test') {
|
|
42
|
-
if((offset + length) * type.BYTES_PER_ELEMENT > this.data.byteLength) {
|
|
43
|
-
const message = `Trying to grab more memory from AllocatedMemory.getArray then we have: ${offset * type.BYTES_PER_ELEMENT} + ${length * type.BYTES_PER_ELEMENT} > ${this.data.byteLength}`;
|
|
44
|
-
if(import.meta.env.MODE === 'test') {
|
|
45
|
-
throw new Error(message);
|
|
46
|
-
} else {
|
|
47
|
-
console.warn(message);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return new type(this.data.buffer, this.data.byteOffset + offset * type.BYTES_PER_ELEMENT, length);
|
|
53
|
-
}
|
|
54
|
-
getArrayMemory(offset: number, length: number): SharedAllocatedMemory {
|
|
55
|
-
if(import.meta.env.MODE === 'development') {
|
|
56
|
-
if(offset + length > this.data.length) {
|
|
57
|
-
console.warn(`Trying to grab more memory from AllocatedMemory.getArrayMemory then we have: ${offset} + ${length} > ${this.data.length}`);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
bufferPosition: this.bufferPosition,
|
|
63
|
-
bufferByteOffset: this.bufferByteOffset + offset * this.data.BYTES_PER_ELEMENT
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
free() {
|
|
68
|
-
// NOTE: From worker thread you can't pass the array, you have to pass an explicit address to free
|
|
69
|
-
this.buffer.free(this.data.byteOffset);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
getSharedMemory(): SharedAllocatedMemory {
|
|
73
|
-
return {
|
|
74
|
-
bufferPosition: this.bufferPosition,
|
|
75
|
-
bufferByteOffset: this.bufferByteOffset
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
interface AllocatedMemoryConfig {
|
|
81
|
-
data: Uint32Array
|
|
82
|
-
buffer: MemoryBuffer
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
interface SharedAllocatedMemory {
|
|
86
|
-
bufferPosition: number
|
|
87
|
-
bufferByteOffset: number
|
|
88
|
-
}
|
|
89
|
-
export type { SharedAllocatedMemory };
|
package/src/cached-item-list.ts
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import type { SharedAllocatedMemory } from './allocated-memory';
|
|
2
|
-
import type MemoryHeap from './memory-heap';
|
|
3
|
-
import SharedList, { type SharedListMemory } from './shared-list';
|
|
4
|
-
|
|
5
|
-
export default abstract class CachedItemList<T extends Item> implements Iterable<{ item: T, deleteCurrent: () => void }> {
|
|
6
|
-
static readonly ALLOCATE_COUNT = SharedList.ALLOCATE_COUNT;
|
|
7
|
-
|
|
8
|
-
protected heap: MemoryHeap;
|
|
9
|
-
protected list: SharedList;
|
|
10
|
-
protected cache: Map<number, T> = new Map();
|
|
11
|
-
|
|
12
|
-
constructor(heap: MemoryHeap, config?: CachedListConfig | SharedListMemory) {
|
|
13
|
-
if(config) {
|
|
14
|
-
this.list = new SharedList(heap, config);
|
|
15
|
-
} else {
|
|
16
|
-
this.list = new SharedList(heap);
|
|
17
|
-
}
|
|
18
|
-
this.heap = heap;
|
|
19
|
-
|
|
20
|
-
this.list.onDelete = (pointerData: Uint32Array) => {
|
|
21
|
-
let pointer = Atomics.load(pointerData, 0);
|
|
22
|
-
if(pointer) {
|
|
23
|
-
let item = this.cache.get(pointer);
|
|
24
|
-
if(!item) {
|
|
25
|
-
item = this.initItem(pointer);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if(item) {
|
|
29
|
-
item.free();
|
|
30
|
-
this.cache.delete(pointer);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
get length() {
|
|
37
|
-
return this.list.length;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
clear() {
|
|
41
|
-
this.list.clear();
|
|
42
|
-
this.cache.clear();
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
insert(item: T) {
|
|
46
|
-
this.list.insert(item.pointer);
|
|
47
|
-
this.cache.set(item.pointer, item);
|
|
48
|
-
}
|
|
49
|
-
delete(item: T) {
|
|
50
|
-
this.cache.delete(item.pointer);
|
|
51
|
-
return this.list.deleteValue(item.pointer);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
getByPointer(pointer: number): T | undefined {
|
|
55
|
-
let item = this.cache.get(pointer);
|
|
56
|
-
if(!item) {
|
|
57
|
-
item = this.initItem(pointer);
|
|
58
|
-
if(item) {
|
|
59
|
-
this.cache.set(pointer, item);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return item;
|
|
64
|
-
}
|
|
65
|
-
protected abstract initItem(pointer: number): T | undefined
|
|
66
|
-
|
|
67
|
-
*[Symbol.iterator]() {
|
|
68
|
-
let iterator = this.list[Symbol.iterator]();
|
|
69
|
-
|
|
70
|
-
for(let { data: pointerData, deleteCurrent } of iterator) {
|
|
71
|
-
let pointer = Atomics.load(pointerData, 0);
|
|
72
|
-
if(!pointer) {
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
let item = this.cache.get(pointer);
|
|
77
|
-
if(!item) {
|
|
78
|
-
item = this.initItem(pointer);
|
|
79
|
-
if(item) {
|
|
80
|
-
this.cache.set(pointer, item);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if(item) {
|
|
85
|
-
yield {
|
|
86
|
-
item,
|
|
87
|
-
deleteCurrent
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
forEach(callback: (item: T) => void, filter?: (item: T) => boolean) {
|
|
93
|
-
for(let { item } of this) {
|
|
94
|
-
if(!filter || filter(item)) {
|
|
95
|
-
callback(item);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
find(callback: (item: T) => boolean): T | undefined {
|
|
101
|
-
for(let { item } of this) {
|
|
102
|
-
if(callback(item)) {
|
|
103
|
-
return item;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
filter(callback: (entity: T) => boolean): Array<T> {
|
|
108
|
-
let items = [];
|
|
109
|
-
for(let { item } of this) {
|
|
110
|
-
if(callback(item)) {
|
|
111
|
-
items.push(item);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return items;
|
|
116
|
-
}
|
|
117
|
-
map<X>(callback: (item: T) => X): Array<X> {
|
|
118
|
-
const array: Array<X> = [];
|
|
119
|
-
for(let { item } of this) {
|
|
120
|
-
array.push(callback(item));
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return array;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
getSharedMemory() {
|
|
127
|
-
return this.list.getSharedMemory();
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
free() {
|
|
131
|
-
this.list.free();
|
|
132
|
-
this.cache.clear();
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export interface CachedListConfig {
|
|
137
|
-
initWithBlock: SharedAllocatedMemory
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
interface Item {
|
|
141
|
-
pointer: number
|
|
142
|
-
free: () => void
|
|
143
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
const UNLOCKED = 0;
|
|
2
|
-
const READ_LOCKED = 1;
|
|
3
|
-
const WRITE_LOCKED = 2;
|
|
4
|
-
|
|
5
|
-
export function readLock(data: Int32Array, index: number = 0) {
|
|
6
|
-
// Wait over and over again until we get that it was unlocked or read locked
|
|
7
|
-
while(Atomics.compareExchange(data, index, UNLOCKED, READ_LOCKED) === WRITE_LOCKED) {
|
|
8
|
-
Atomics.wait(data, index, WRITE_LOCKED);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
Atomics.add(data, index + 1, 1);
|
|
12
|
-
}
|
|
13
|
-
export function writeLock(data: Int32Array, index: number = 0) {
|
|
14
|
-
// Write lock needs to be exclusive - wait until we were in UNLOCKED to proceed
|
|
15
|
-
let oldValue = Atomics.compareExchange(data, index, UNLOCKED, WRITE_LOCKED);
|
|
16
|
-
while(oldValue !== UNLOCKED) {
|
|
17
|
-
Atomics.wait(data, index, oldValue);
|
|
18
|
-
oldValue = Atomics.compareExchange(data, index, UNLOCKED, WRITE_LOCKED);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function readUnlock(data: Int32Array, index: number = 0) {
|
|
23
|
-
let readCount = Atomics.sub(data, index + 1, 1) - 1;
|
|
24
|
-
|
|
25
|
-
if(readCount <= 0) {
|
|
26
|
-
if(Atomics.compareExchange(data, index, READ_LOCKED, UNLOCKED) !== READ_LOCKED) {
|
|
27
|
-
console.warn('We are unlocking when it was not read locked!');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
Atomics.notify(data, index);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
export function writeUnlock(data: Int32Array, index: number = 0) {
|
|
34
|
-
if(Atomics.compareExchange(data, index, WRITE_LOCKED, UNLOCKED) !== WRITE_LOCKED) {
|
|
35
|
-
console.warn('We are unlocking when it was not write locked!');
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
Atomics.notify(data, index);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export const READ_WRITE_LOCK_ALLOCATE_COUNT = 2;
|
package/src/lock/simple-lock.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
const UNLOCKED = 0;
|
|
2
|
-
const LOCKED = 1;
|
|
3
|
-
export function lock(data: Int32Array, index: number = 0) {
|
|
4
|
-
// Wait over and over again until we are one who set this from UNLOCKED to LOCKED
|
|
5
|
-
while(Atomics.compareExchange(data, index, UNLOCKED, LOCKED) !== UNLOCKED) {
|
|
6
|
-
if('WorkerGlobalScope' in self) {
|
|
7
|
-
Atomics.wait(data, index, LOCKED);
|
|
8
|
-
} else {
|
|
9
|
-
// TODO: Spin-locks suck....
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
export function unlock(data: Int32Array, index: number = 0) {
|
|
14
|
-
if(Atomics.compareExchange(data, index, LOCKED, UNLOCKED) !== LOCKED) {
|
|
15
|
-
console.warn('We are unlocking when it was not locked!');
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
Atomics.notify(data, index);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export const SIMPLE_LOCK_ALLOCATE_COUNT = 1;
|
package/src/main.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import AllocatedMemory, { type SharedAllocatedMemory } from './allocated-memory';
|
|
2
|
-
import MemoryBuffer from './memory-buffer';
|
|
3
|
-
import MemoryHeap, { type MemoryHeapMemory, type GrowBufferData } from './memory-heap';
|
|
4
|
-
|
|
5
|
-
import SharedList, { type SharedListMemory } from './shared-list';
|
|
6
|
-
import SharedMap, { type SharedMapMemory } from './shared-map';
|
|
7
|
-
import SharedPointerList from './shared-pointer-list';
|
|
8
|
-
import SharedString from './shared-string';
|
|
9
|
-
import SharedVector, { type SharedVectorMemory } from './shared-vector';
|
|
10
|
-
import CachedItemList, { type CachedListConfig } from './cached-item-list';
|
|
11
|
-
|
|
12
|
-
export * from './interfaces/typed-array';
|
|
13
|
-
export * from './interfaces/typed-array-constructor';
|
|
14
|
-
|
|
15
|
-
export * from './utils/16-from-32-array';
|
|
16
|
-
export * from './utils/16-from-64-array';
|
|
17
|
-
export * from './utils/float32-atomics';
|
|
18
|
-
export * from './utils/pointer';
|
|
19
|
-
export * from './lock/simple-lock';
|
|
20
|
-
export * from './lock/read-write-lock';
|
|
21
|
-
|
|
22
|
-
export {
|
|
23
|
-
AllocatedMemory,
|
|
24
|
-
type SharedAllocatedMemory,
|
|
25
|
-
MemoryBuffer,
|
|
26
|
-
MemoryHeap,
|
|
27
|
-
type MemoryHeapMemory,
|
|
28
|
-
type GrowBufferData,
|
|
29
|
-
|
|
30
|
-
SharedList,
|
|
31
|
-
type SharedListMemory,
|
|
32
|
-
SharedMap,
|
|
33
|
-
type SharedMapMemory,
|
|
34
|
-
SharedPointerList,
|
|
35
|
-
SharedString,
|
|
36
|
-
SharedVector,
|
|
37
|
-
type SharedVectorMemory,
|
|
38
|
-
CachedItemList,
|
|
39
|
-
type CachedListConfig
|
|
40
|
-
};
|