@daneren2005/shared-memory-objects 0.0.10 → 0.0.12
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/README.md +82 -3
- package/dist/shared-memory-objects.js +1356 -0
- package/dist/shared-memory-objects.js.map +1 -0
- package/dist/shared-memory-objects.umd.cjs +2 -0
- package/dist/shared-memory-objects.umd.cjs.map +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-pool.d.ts +39 -0
- package/dist/src/shared-string.d.ts +23 -0
- package/dist/src/shared-vector.d.ts +41 -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 +34 -22
- 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
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { default as AllocatedMemory, SharedAllocatedMemory } from './allocated-memory';
|
|
2
|
+
import { default as MemoryBuffer } from './memory-buffer';
|
|
3
|
+
export default class MemoryHeap {
|
|
4
|
+
buffers: Array<MemoryBuffer>;
|
|
5
|
+
private onGrowBufferHandlers;
|
|
6
|
+
isClone: boolean;
|
|
7
|
+
private memory;
|
|
8
|
+
get bufferSize(): number;
|
|
9
|
+
constructor(config?: MemoryHeapConfig | MemoryHeapMemory);
|
|
10
|
+
addSharedBuffer(data: GrowBufferData): void;
|
|
11
|
+
private growBuffer;
|
|
12
|
+
private createBuffer;
|
|
13
|
+
addOnGrowBufferHandlers(handler: OnGrowBuffer): void;
|
|
14
|
+
allocUI32(count: number): AllocatedMemory;
|
|
15
|
+
getSharedAlloc(shared: SharedAllocatedMemory): AllocatedMemory | undefined;
|
|
16
|
+
get currentUsed(): number;
|
|
17
|
+
get totalAllocated(): number;
|
|
18
|
+
prettyMemory(): string;
|
|
19
|
+
getSharedMemory(): MemoryHeapMemory;
|
|
20
|
+
}
|
|
21
|
+
type OnGrowBuffer = (newBuffer: GrowBufferData) => void;
|
|
22
|
+
interface GrowBufferData {
|
|
23
|
+
bufferPosition: number;
|
|
24
|
+
buffer: SharedArrayBuffer;
|
|
25
|
+
}
|
|
26
|
+
interface MemoryHeapConfig {
|
|
27
|
+
bufferSize?: number;
|
|
28
|
+
initialBuffers?: number;
|
|
29
|
+
autoGrowSize?: number;
|
|
30
|
+
}
|
|
31
|
+
interface MemoryHeapMemory {
|
|
32
|
+
buffers: Array<SharedArrayBuffer>;
|
|
33
|
+
}
|
|
34
|
+
export type { MemoryHeapConfig, MemoryHeapMemory, GrowBufferData };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { default as AllocatedMemory } from './allocated-memory';
|
|
2
|
+
import { default as MemoryHeap } from './memory-heap';
|
|
3
|
+
export declare function serializeObjectToMemory<T extends object>(heap: MemoryHeap, object: T): AllocatedMemory;
|
|
4
|
+
export declare function createObjectFromPointer<T extends object>(heap: MemoryHeap, pointer: number): T;
|
|
5
|
+
export declare function createObjectFromMemory<T extends object>(memory: AllocatedMemory): T;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { SharedAllocatedMemory } from './allocated-memory';
|
|
2
|
+
import { TypedArrayConstructor } from './interfaces/typed-array-constructor';
|
|
3
|
+
import { default as MemoryHeap } from './memory-heap';
|
|
4
|
+
export default class SharedList<T extends Uint32Array | Int32Array | Float32Array = Uint32Array> implements Iterable<SharedListIterable<T>> {
|
|
5
|
+
static readonly ALLOCATE_COUNT = 4;
|
|
6
|
+
private memory;
|
|
7
|
+
private firstBlock;
|
|
8
|
+
private uint16Array;
|
|
9
|
+
onDelete?: (data: T) => void;
|
|
10
|
+
get length(): number;
|
|
11
|
+
get type(): number;
|
|
12
|
+
private set type(value);
|
|
13
|
+
get dataLength(): number;
|
|
14
|
+
private set dataLength(value);
|
|
15
|
+
constructor(memory: MemoryHeap, config?: SharedListConfig<T> | SharedListMemory);
|
|
16
|
+
insert(values: number | Array<number>): void;
|
|
17
|
+
deleteMatch(callback: (values: T, index: number) => boolean): boolean;
|
|
18
|
+
deleteIndex(deleteIndex: number): boolean;
|
|
19
|
+
deleteValue(deleteValues: number | Array<number>): boolean;
|
|
20
|
+
clear(): void;
|
|
21
|
+
[Symbol.iterator](): Generator<{
|
|
22
|
+
data: T;
|
|
23
|
+
index: number;
|
|
24
|
+
deleteCurrent: () => void;
|
|
25
|
+
}, void, unknown>;
|
|
26
|
+
forEach(callback: (data: T) => void): void;
|
|
27
|
+
getSharedMemory(): SharedListMemory;
|
|
28
|
+
private getDataBlock;
|
|
29
|
+
free(): void;
|
|
30
|
+
}
|
|
31
|
+
interface SharedListConfig<T extends Uint32Array | Int32Array | Float32Array> {
|
|
32
|
+
initWithBlock?: SharedAllocatedMemory;
|
|
33
|
+
type?: TypedArrayConstructor<T>;
|
|
34
|
+
dataLength?: number;
|
|
35
|
+
}
|
|
36
|
+
interface SharedListMemory {
|
|
37
|
+
firstBlock: SharedAllocatedMemory;
|
|
38
|
+
}
|
|
39
|
+
interface SharedListIterable<T extends Uint32Array | Int32Array | Float32Array> {
|
|
40
|
+
data: T;
|
|
41
|
+
index: number;
|
|
42
|
+
deleteCurrent: () => void;
|
|
43
|
+
}
|
|
44
|
+
export { type SharedListMemory };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SharedAllocatedMemory } from './allocated-memory';
|
|
2
|
+
import { default as MemoryHeap } from './memory-heap';
|
|
3
|
+
export default class SharedMap<K extends string | number> {
|
|
4
|
+
static readonly ALLOCATE_COUNT = 4;
|
|
5
|
+
private memory;
|
|
6
|
+
private pointerMemory;
|
|
7
|
+
private lock;
|
|
8
|
+
private get hashMemory();
|
|
9
|
+
get length(): number;
|
|
10
|
+
get maxHash(): number;
|
|
11
|
+
constructor(memory: MemoryHeap, clone?: SharedMapMemory);
|
|
12
|
+
set(key: K, value: number): void;
|
|
13
|
+
private setHashKey;
|
|
14
|
+
get(key: K): number | undefined;
|
|
15
|
+
has(key: K): boolean;
|
|
16
|
+
delete(key: K): boolean;
|
|
17
|
+
private growHashTable;
|
|
18
|
+
private hash;
|
|
19
|
+
free(): void;
|
|
20
|
+
getSharedMemory(): SharedMapMemory;
|
|
21
|
+
}
|
|
22
|
+
interface SharedMapMemory {
|
|
23
|
+
firstBlock: SharedAllocatedMemory;
|
|
24
|
+
}
|
|
25
|
+
export type { SharedMapMemory };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { default as AllocatedMemory } from './allocated-memory';
|
|
2
|
+
import { default as MemoryHeap } from './memory-heap';
|
|
3
|
+
import { SharedListMemory } from './shared-list';
|
|
4
|
+
export default abstract class SharedPointerList<T extends PointerItem> implements Iterable<T> {
|
|
5
|
+
private memory;
|
|
6
|
+
private list;
|
|
7
|
+
constructor(heap: MemoryHeap, memory?: SharedListMemory);
|
|
8
|
+
get length(): number;
|
|
9
|
+
insert(item: T): void;
|
|
10
|
+
delete(item: T): boolean;
|
|
11
|
+
[Symbol.iterator](): Generator<T, void, unknown>;
|
|
12
|
+
forEach(callback: (item: T) => void): void;
|
|
13
|
+
find(callback: (item: T) => boolean): T | undefined;
|
|
14
|
+
getSharedMemory(): SharedListMemory;
|
|
15
|
+
protected abstract createItem(allocatedMemory: AllocatedMemory): T;
|
|
16
|
+
free(): void;
|
|
17
|
+
}
|
|
18
|
+
interface PointerItem {
|
|
19
|
+
readonly memory: AllocatedMemory;
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { SharedAllocatedMemory } from './allocated-memory';
|
|
2
|
+
import { TypedArrayConstructor } from './interfaces/typed-array-constructor';
|
|
3
|
+
import { default as MemoryHeap } from './memory-heap';
|
|
4
|
+
export default class SharedPool<T extends Uint32Array | Int32Array | Float32Array = Uint32Array> implements Iterable<T> {
|
|
5
|
+
static readonly ALLOCATE_COUNT: number;
|
|
6
|
+
private memory;
|
|
7
|
+
private firstBlock;
|
|
8
|
+
private uint16Array;
|
|
9
|
+
private pointerVector;
|
|
10
|
+
private recycleVector;
|
|
11
|
+
private cachedFullDataBlock;
|
|
12
|
+
get length(): number;
|
|
13
|
+
get maxChunkSize(): number;
|
|
14
|
+
private set maxChunkSize(value);
|
|
15
|
+
get type(): number;
|
|
16
|
+
private set type(value);
|
|
17
|
+
get dataLength(): number;
|
|
18
|
+
private set dataLength(value);
|
|
19
|
+
constructor(memory: MemoryHeap, config?: SharedPoolConfig<T> | SharedPoolMemory);
|
|
20
|
+
at(index: number): T;
|
|
21
|
+
get(index: number, dataIndex?: number): number;
|
|
22
|
+
push(values: number | Array<number>): number;
|
|
23
|
+
deleteIndex(index: number): void;
|
|
24
|
+
clear(): void;
|
|
25
|
+
[Symbol.iterator](): Generator<T, void, unknown>;
|
|
26
|
+
private getFullDataBlock;
|
|
27
|
+
private getDataBlock;
|
|
28
|
+
free(): void;
|
|
29
|
+
getSharedMemory(): SharedPoolMemory;
|
|
30
|
+
}
|
|
31
|
+
interface SharedPoolConfig<T extends Uint32Array | Int32Array | Float32Array> {
|
|
32
|
+
maxChunkSize?: number;
|
|
33
|
+
type?: TypedArrayConstructor<T>;
|
|
34
|
+
dataLength?: number;
|
|
35
|
+
}
|
|
36
|
+
interface SharedPoolMemory {
|
|
37
|
+
firstBlock: SharedAllocatedMemory;
|
|
38
|
+
}
|
|
39
|
+
export type { SharedPoolConfig, SharedPoolMemory };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SharedAllocatedMemory } from './allocated-memory';
|
|
2
|
+
import { default as MemoryHeap } from './memory-heap';
|
|
3
|
+
export default class SharedString {
|
|
4
|
+
static readonly ALLOCATE_COUNT = 4;
|
|
5
|
+
private memory;
|
|
6
|
+
private allocatedMemory;
|
|
7
|
+
private lock;
|
|
8
|
+
private cachedPointer?;
|
|
9
|
+
private cachedString?;
|
|
10
|
+
constructor(memory: MemoryHeap, value: string | SharedStringConfig | SharedStringMemory);
|
|
11
|
+
private updateString;
|
|
12
|
+
private createString;
|
|
13
|
+
get value(): string;
|
|
14
|
+
set value(value: string);
|
|
15
|
+
getSharedMemory(): SharedStringMemory;
|
|
16
|
+
get pointer(): number;
|
|
17
|
+
free(): void;
|
|
18
|
+
}
|
|
19
|
+
interface SharedStringConfig extends SharedStringMemory {
|
|
20
|
+
value: string;
|
|
21
|
+
}
|
|
22
|
+
type SharedStringMemory = SharedAllocatedMemory;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { SharedAllocatedMemory } from './allocated-memory';
|
|
2
|
+
import { TypedArrayConstructor } from './interfaces/typed-array-constructor';
|
|
3
|
+
import { default as MemoryHeap } from './memory-heap';
|
|
4
|
+
export default class SharedVector<T extends Uint32Array | Int32Array | Float32Array = Uint32Array> implements Iterable<T> {
|
|
5
|
+
static readonly ALLOCATE_COUNT = 4;
|
|
6
|
+
private memory;
|
|
7
|
+
private firstBlock;
|
|
8
|
+
private uint16Array;
|
|
9
|
+
get length(): number;
|
|
10
|
+
get type(): number;
|
|
11
|
+
private set type(value);
|
|
12
|
+
get dataLength(): number;
|
|
13
|
+
private set dataLength(value);
|
|
14
|
+
get bufferLength(): number;
|
|
15
|
+
private set bufferLength(value);
|
|
16
|
+
get pointer(): number;
|
|
17
|
+
private cachedFullDataBlock?;
|
|
18
|
+
private cachedPointer;
|
|
19
|
+
constructor(memory: MemoryHeap, config?: SharedVectorConfig<T> | SharedVectorMemory | SharedVectorMemory & SharedVectorConfig<T>);
|
|
20
|
+
at(index: number): T;
|
|
21
|
+
get(index: number, dataIndex?: number): number;
|
|
22
|
+
push(values: number | Array<number>): number;
|
|
23
|
+
pop(): T;
|
|
24
|
+
deleteIndex(index: number): void;
|
|
25
|
+
clear(): void;
|
|
26
|
+
[Symbol.iterator](): Generator<T, void, unknown>;
|
|
27
|
+
private getFullDataBlock;
|
|
28
|
+
private getDataBlock;
|
|
29
|
+
private growBuffer;
|
|
30
|
+
free(): void;
|
|
31
|
+
getSharedMemory(): SharedVectorMemory;
|
|
32
|
+
}
|
|
33
|
+
interface SharedVectorConfig<T extends Uint32Array | Int32Array | Float32Array> {
|
|
34
|
+
type?: TypedArrayConstructor<T>;
|
|
35
|
+
dataLength?: number;
|
|
36
|
+
bufferLength?: number;
|
|
37
|
+
}
|
|
38
|
+
interface SharedVectorMemory {
|
|
39
|
+
firstBlock: SharedAllocatedMemory;
|
|
40
|
+
}
|
|
41
|
+
export type { SharedVectorConfig, SharedVectorMemory };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function load16From32(data: Uint32Array, index: number): [number, number];
|
|
2
|
+
export declare function store16In32(data: Uint32Array, index: number, value1: number, value2: number): void;
|
|
3
|
+
export declare function convert32To16(value: number): [number, number];
|
|
4
|
+
export declare function convert16To32(value1: number, value2: number): number;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function loadFloat32(data: Int32Array | Uint32Array, index: number): number;
|
|
2
|
+
export declare function storeFloat32(data: Int32Array | Uint32Array, index: number, value: number): void;
|
|
3
|
+
export declare function convertInt32ToFloat32(value: number): number;
|
|
4
|
+
export declare function convertFloat32ToInt32(value: number): number;
|
|
5
|
+
export declare function exchangeFloat32(data: Int32Array | Uint32Array, index: number, value: number): number;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
declare const BYTE_OFFSET_BIT_COUNT = 20;
|
|
2
|
+
declare const POSITION_BIT_COUNT: number;
|
|
3
|
+
declare const MAX_BYTE_OFFSET_LENGTH: number;
|
|
4
|
+
declare const MAX_POSITION_LENGTH: number;
|
|
5
|
+
export declare function loadPointer(data: Uint32Array, index?: number): {
|
|
6
|
+
bufferPosition: number;
|
|
7
|
+
bufferByteOffset: number;
|
|
8
|
+
};
|
|
9
|
+
export declare function loadRawPointer(data: Uint32Array, index?: number): number;
|
|
10
|
+
export declare function storePointer(data: Uint32Array, index: number | undefined, bufferPosition: number, bufferByteOffset: number): void;
|
|
11
|
+
export declare function storeRawPointer(data: Uint32Array, index: number | undefined, pointer: number): void;
|
|
12
|
+
export declare function replacePointer(data: Uint32Array, index: number, newBufferPosition: number, newBufferByteOffset: number, oldBufferPosition: number, oldBufferByteOffset: number): boolean;
|
|
13
|
+
export declare function replaceRawPointer(data: Uint32Array, index: number, newPointer: number, oldPointer: number): boolean;
|
|
14
|
+
export declare function getPointer(value: number): {
|
|
15
|
+
bufferPosition: number;
|
|
16
|
+
bufferByteOffset: number;
|
|
17
|
+
};
|
|
18
|
+
export declare function createPointer(bufferPosition: number, bufferByteOffset: number): number;
|
|
19
|
+
export { BYTE_OFFSET_BIT_COUNT, POSITION_BIT_COUNT, MAX_BYTE_OFFSET_LENGTH, MAX_POSITION_LENGTH };
|
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.12",
|
|
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,16 +17,27 @@
|
|
|
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
|
+
"types": "./dist/src/main.d.ts",
|
|
27
|
+
"default": "./dist/shared-memory-objects.js"
|
|
28
|
+
},
|
|
29
|
+
"require": {
|
|
30
|
+
"types": "./dist/src/main.d.ts",
|
|
31
|
+
"default": "./dist/shared-memory-objects.js"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
26
34
|
},
|
|
35
|
+
"types": "./dist/src/main.d.ts",
|
|
27
36
|
"scripts": {
|
|
37
|
+
"build": "vite build",
|
|
28
38
|
"dev": "vite",
|
|
29
|
-
"lint": "eslint
|
|
39
|
+
"lint": "eslint",
|
|
40
|
+
"lint:fix": "eslint --fix",
|
|
30
41
|
"preview": "vite preview",
|
|
31
42
|
"publish": "npm publish --access public",
|
|
32
43
|
"start": "npm run dev",
|
|
@@ -38,23 +49,24 @@
|
|
|
38
49
|
"prepare": "husky"
|
|
39
50
|
},
|
|
40
51
|
"devDependencies": {
|
|
41
|
-
"@
|
|
42
|
-
"@tsconfig/
|
|
43
|
-
"@types/jsdom": "^
|
|
44
|
-
"@types/node": "^
|
|
45
|
-
"@vitest/coverage-v8": "^
|
|
46
|
-
"@vitest/
|
|
47
|
-
"
|
|
48
|
-
"eslint
|
|
49
|
-
"husky": "^9.
|
|
50
|
-
"jsdom": "^
|
|
51
|
-
"lint-staged": "^
|
|
52
|
-
"typescript": "^5.
|
|
53
|
-
"typescript-eslint": "^
|
|
54
|
-
"
|
|
55
|
-
"
|
|
52
|
+
"@microsoft/api-extractor": "^7.53.2",
|
|
53
|
+
"@tsconfig/node24": "^24.0.1",
|
|
54
|
+
"@types/jsdom": "^27.0.0",
|
|
55
|
+
"@types/node": "^24.9.1",
|
|
56
|
+
"@vitest/coverage-v8": "^4.0.1",
|
|
57
|
+
"@vitest/eslint-plugin": "^1.3.23",
|
|
58
|
+
"@vitest/ui": "^4.0.1",
|
|
59
|
+
"eslint": "^9.38.0",
|
|
60
|
+
"husky": "^9.1.7",
|
|
61
|
+
"jsdom": "^27.0.1",
|
|
62
|
+
"lint-staged": "^16.2.6",
|
|
63
|
+
"typescript": "^5.9.3",
|
|
64
|
+
"typescript-eslint": "^8.46.2",
|
|
65
|
+
"unplugin-dts": "^1.0.0-beta.6",
|
|
66
|
+
"vite": "^7.1.11",
|
|
67
|
+
"vitest": "^4.0.1"
|
|
56
68
|
},
|
|
57
69
|
"dependencies": {
|
|
58
|
-
"pretty-bytes": "^
|
|
70
|
+
"pretty-bytes": "^7.1.0"
|
|
59
71
|
}
|
|
60
72
|
}
|
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;
|