@daneren2005/shared-memory-objects 1.1.0 → 1.2.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/README.md +78 -55
- package/dist/{src/allocated-memory.d.ts → allocated-memory.d.ts} +5 -4
- package/dist/allocated-memory.js +44 -37
- package/dist/allocated-memory.js.map +1 -1
- package/dist/{src/cached-item-list.d.ts → cached-item-list.d.ts} +3 -3
- package/dist/cached-item-list.js +70 -75
- package/dist/cached-item-list.js.map +1 -1
- package/dist/constant-string.d.ts +15 -0
- package/dist/constant-string.js +67 -0
- package/dist/constant-string.js.map +1 -0
- package/dist/interfaces/pow2.js +0 -2
- package/dist/interfaces/typed-array-constructor.js +0 -2
- package/dist/interfaces/typed-array.js +0 -2
- package/dist/{src/local-pool.d.ts → local-pool.d.ts} +2 -2
- package/dist/local-pool.js +89 -94
- package/dist/local-pool.js.map +1 -1
- package/dist/lock/read-write-lock.js +15 -21
- package/dist/lock/read-write-lock.js.map +1 -1
- package/dist/lock/simple-lock.js +9 -12
- package/dist/lock/simple-lock.js.map +1 -1
- package/dist/{src/memory-buffer.d.ts → memory-buffer.d.ts} +4 -4
- package/dist/memory-buffer.js +266 -326
- package/dist/memory-buffer.js.map +1 -1
- package/dist/{src/memory-heap.d.ts → memory-heap.d.ts} +2 -2
- package/dist/memory-heap.js +95 -115
- package/dist/memory-heap.js.map +1 -1
- package/dist/{src/serialize-object.d.ts → serialize-object.d.ts} +2 -2
- package/dist/serialize-object.js +43 -55
- package/dist/serialize-object.js.map +1 -1
- package/dist/{src/shared-list.d.ts → shared-list.d.ts} +3 -3
- package/dist/shared-list.js +124 -164
- package/dist/shared-list.js.map +1 -1
- package/dist/{src/shared-map.d.ts → shared-map.d.ts} +2 -2
- package/dist/shared-map.js +102 -138
- package/dist/shared-map.js.map +1 -1
- package/dist/{src/shared-pointer-list.d.ts → shared-pointer-list.d.ts} +3 -3
- package/dist/shared-pointer-list.js +45 -48
- package/dist/shared-pointer-list.js.map +1 -1
- package/dist/{src/shared-pool.d.ts → shared-pool.d.ts} +11 -8
- package/dist/shared-pool.js +144 -164
- package/dist/shared-pool.js.map +1 -1
- package/dist/shared-stack.d.ts +46 -0
- package/dist/shared-stack.js +144 -0
- package/dist/shared-stack.js.map +1 -0
- package/dist/{src/shared-string.d.ts → shared-string.d.ts} +2 -2
- package/dist/shared-string.js +72 -78
- package/dist/shared-string.js.map +1 -1
- package/dist/{src/shared-vector.d.ts → shared-vector.d.ts} +4 -4
- package/dist/shared-vector.js +146 -164
- package/dist/shared-vector.js.map +1 -1
- package/dist/utils/16-from-32-array.js +14 -16
- package/dist/utils/16-from-32-array.js.map +1 -1
- package/dist/utils/16-from-64-array.js +15 -10
- package/dist/utils/16-from-64-array.js.map +1 -1
- package/dist/utils/atomic-math.js +30 -32
- package/dist/utils/atomic-math.js.map +1 -1
- package/dist/utils/float32-atomics.js +18 -22
- package/dist/utils/float32-atomics.js.map +1 -1
- package/dist/utils/float64-atomics.js +18 -22
- package/dist/utils/float64-atomics.js.map +1 -1
- package/dist/utils/pointer.js +34 -44
- package/dist/utils/pointer.js.map +1 -1
- package/dist/{src/utils → utils}/typedarray.d.ts +47 -47
- package/dist/utils/typedarray.js +36 -43
- package/dist/utils/typedarray.js.map +1 -1
- package/package.json +22 -22
- package/dist/interfaces/pow2.js.map +0 -1
- package/dist/interfaces/typed-array-constructor.js.map +0 -1
- package/dist/interfaces/typed-array.js.map +0 -1
- /package/dist/{src/interfaces → interfaces}/pow2.d.ts +0 -0
- /package/dist/{src/interfaces → interfaces}/typed-array-constructor.d.ts +0 -0
- /package/dist/{src/interfaces → interfaces}/typed-array.d.ts +0 -0
- /package/dist/{src/lock → lock}/read-write-lock.d.ts +0 -0
- /package/dist/{src/lock → lock}/simple-lock.d.ts +0 -0
- /package/dist/{src/utils → utils}/16-from-32-array.d.ts +0 -0
- /package/dist/{src/utils → utils}/16-from-64-array.d.ts +0 -0
- /package/dist/{src/utils → utils}/atomic-math.d.ts +0 -0
- /package/dist/{src/utils → utils}/float32-atomics.d.ts +0 -0
- /package/dist/{src/utils → utils}/float64-atomics.d.ts +0 -0
- /package/dist/{src/utils → utils}/pointer.d.ts +0 -0
package/dist/shared-map.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-map.js","sources":["../src/shared-map.ts"],"sourcesContent":["import AllocatedMemory, { type SharedAllocatedMemory } from './allocated-memory';\nimport type MemoryHeap from './memory-heap';\nimport SharedList from './shared-list';\nimport { loadPointer, storePointer } from './utils/pointer';\n\n// TODO: Grow hashMemory\n// TODO: Add iterator\n// TODO: Add read/write locks\nconst DEFAULT_HASH_SIZE = 10;\nexport default class SharedMap<K extends string | number> {\n\tstatic readonly ALLOCATE_COUNT = 4;\n\n\tprivate memory: MemoryHeap;\n\t// Memory order: Pointer, Lock, Length, MaxHash\n\tprivate pointerMemory: AllocatedMemory;\n\tprivate lock: Int32Array;\n\tprivate get hashMemory(): AllocatedMemory {\n\t\treturn new AllocatedMemory(this.memory, loadPointer(this.pointerMemory.data, 0));\n\t}\n\n\tget length(): number {\n\t\treturn Atomics.load(this.pointerMemory.data, 2);\n\t}\n\tget maxHash(): number {\n\t\treturn Atomics.load(this.pointerMemory.data, 3);\n\t}\n\n\tconstructor(memory: MemoryHeap, clone?: SharedMapMemory) {\n\t\tthis.memory = memory;\n\n\t\tif(clone) {\n\t\t\tthis.pointerMemory = new AllocatedMemory(memory, clone.firstBlock);\n\t\t} else {\n\t\t\tthis.pointerMemory = memory.allocUI32(SharedMap.ALLOCATE_COUNT);\n\t\t\tlet hashMemory = memory.allocUI32(DEFAULT_HASH_SIZE);\n\t\t\tstorePointer(this.pointerMemory.data, 0, hashMemory.bufferPosition, hashMemory.bufferByteOffset);\n\t\t\tAtomics.store(this.pointerMemory.data, 3, DEFAULT_HASH_SIZE);\n\t\t}\n\t\tthis.lock = new Int32Array(this.pointerMemory.data.buffer, this.pointerMemory.bufferByteOffset + Uint32Array.BYTES_PER_ELEMENT, 1);\n\t}\n\n\tset(key: K, value: number) {\n\t\tif(this.length >= this.maxHash * 2) {\n\t\t\tthis.growHashTable();\n\t\t}\n\n\t\tlet fullHashKey = get32BitHash(key);\n\t\tif(this.setHashKey(this.hashMemory, this.maxHash, fullHashKey, value)) {\n\t\t\tAtomics.add(this.pointerMemory.data, 2, 1);\n\t\t}\n\t}\n\tprivate setHashKey(hashMemory: AllocatedMemory, maxHash: number, fullHashKey: number, value: number) {\n\t\tlet hashKey = this.hash(fullHashKey, maxHash);\n\t\t\n\t\tlet list: SharedList;\n\t\tlet pointer = loadPointer(hashMemory.data, hashKey);\n\t\tif(pointer.bufferByteOffset === 0) {\n\t\t\t// Initialize a list here\n\t\t\tlist = new SharedList(this.memory, {\n\t\t\t\tdataLength: 2\n\t\t\t});\n\n\t\t\tlet listMemory = list.getSharedMemory();\n\t\t\tstorePointer(hashMemory.data, hashKey, listMemory.firstBlock.bufferPosition, listMemory.firstBlock.bufferByteOffset);\n\t\t} else {\n\t\t\tlist = new SharedList(this.memory, {\n\t\t\t\tfirstBlock: pointer\n\t\t\t});\n\t\t}\n\n\t\t// Check if any other items in list have the same key and delete them\n\t\tlet inserted = true;\n\t\tif(list.deleteValue(fullHashKey)) {\n\t\t\tinserted = false;\n\t\t}\n\t\tlist.insert([fullHashKey, value]);\n\t\t\n\t\treturn inserted;\n\t}\n\n\tget(key: K): number | undefined {\n\t\tlet fullHashKey = get32BitHash(key);\n\t\tlet hashKey = this.hash(fullHashKey, this.maxHash);\n\n\t\tlet pointer = loadPointer(this.hashMemory.data, hashKey);\n\t\tif(pointer.bufferByteOffset === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tlet list = new SharedList(this.memory, {\n\t\t\tfirstBlock: pointer\n\t\t});\n\n\t\tfor(let { data } of list) {\n\t\t\tif(data[0] === fullHashKey) {\n\t\t\t\treturn data[1];\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n\thas(key: K): boolean {\n\t\tlet fullHashKey = get32BitHash(key);\n\t\tlet hashKey = this.hash(fullHashKey, this.maxHash);\n\n\t\tlet pointer = loadPointer(this.hashMemory.data, hashKey);\n\t\tif(pointer.bufferByteOffset === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tlet list = new SharedList(this.memory, {\n\t\t\tfirstBlock: pointer\n\t\t});\n\n\t\tfor(let { data } of list) {\n\t\t\tif(data[0] === fullHashKey) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tdelete(key: K): boolean {\n\t\tlet fullHashKey = get32BitHash(key);\n\t\tlet hashKey = this.hash(fullHashKey, this.maxHash);\n\n\t\tlet pointer = loadPointer(this.hashMemory.data, hashKey);\n\t\tif(pointer.bufferByteOffset === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tlet list = new SharedList(this.memory, {\n\t\t\tfirstBlock: pointer\n\t\t});\n\n\t\tfor(let { data, deleteCurrent } of list) {\n\t\t\tif(data[0] === fullHashKey) {\n\t\t\t\tdeleteCurrent();\n\n\t\t\t\tAtomics.sub(this.pointerMemory.data, 2, 1);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate growHashTable() {\n\t\tlet oldMaxHash = this.maxHash;\n\t\tlet newMaxHash = oldMaxHash * 2;\n\t\tlet newHashMemory = this.memory.allocUI32(newMaxHash);\n\t\tlet oldHashMemory = this.hashMemory;\n\n\t\t// Copy each old hash value into new hash memory\n\t\tfor(let i = 0; i < oldMaxHash; i++) {\n\t\t\tlet pointer = loadPointer(oldHashMemory.data, i);\n\t\t\tif(pointer.bufferByteOffset === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet list = new SharedList(this.memory, {\n\t\t\t\tfirstBlock: pointer\n\t\t\t});\n\t\t\tfor(let { data } of list) {\n\t\t\t\tthis.setHashKey(newHashMemory, newMaxHash, data[0], data[1]);\n\t\t\t}\n\n\t\t\t// The entries have been copied into freshly allocated lists in the new hash table so the old list can be freed\n\t\t\tlist.free();\n\t\t}\n\n\t\tstorePointer(this.pointerMemory.data, 0, newHashMemory.bufferPosition, newHashMemory.bufferByteOffset);\n\t\tAtomics.store(this.pointerMemory.data, 3, newMaxHash);\n\n\t\t// pointerMemory now references newHashMemory so the old hash table memory can be freed\n\t\toldHashMemory.free();\n\t}\n\n\tprivate hash(key: number, maxHash: number) {\n\t\treturn key % maxHash;\n\t}\n\n\tfree() {\n\t\t// Loop through and free lists in hash table first\n\t\tfor(let i = 0; i < this.maxHash; i++) {\n\t\t\tlet pointer = loadPointer(this.hashMemory.data, i);\n\t\t\tif(pointer.bufferByteOffset === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet list = new SharedList(this.memory, {\n\t\t\t\tfirstBlock: pointer\n\t\t\t});\n\t\t\tlist.free();\n\t\t}\n\n\t\tthis.hashMemory.free();\n\t\tthis.pointerMemory.free();\n\t}\n\n\tgetSharedMemory(): SharedMapMemory {\n\t\treturn {\n\t\t\tfirstBlock: this.pointerMemory.getSharedMemory()\n\t\t};\n\t}\n}\n\ninterface SharedMapMemory {\n\tfirstBlock: SharedAllocatedMemory\n}\n\nfunction get32BitHash<K extends string | number>(key: K): number {\n\tif(typeof key === 'number') {\n\t\treturn key;\n\t} else if(typeof key === 'string') {\n\t\treturn hashString(key as string);\n\t} else {\n\t\treturn key;\n\t}\n}\n\n// Copied from https://github.com/mmomtchev/SharedMap/blob/master/index.js - MurmurHash2\nfunction hashString(str: string): number {\n\tlet\n\t\tl = str.length,\n\t\th = 17 ^ l,\n\t\ti = 0,\n\t\tk;\n\twhile(l >= 4) {\n\t\tk =\n\t\t\t((str.charCodeAt(i) & 0xff)) |\n\t\t\t((str.charCodeAt(++i) & 0xff) << 8) |\n\t\t\t((str.charCodeAt(++i) & 0xff) << 16) |\n\t\t\t((str.charCodeAt(++i) & 0xff) << 14);\n\t\tk = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));\n\t\tk ^= k >>> 14;\n\t\tk = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));\n\t\th = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;\n\t\tl -= 4;\n\t\t++i;\n\t}\n\t/* eslint-disable no-fallthrough */\n\tswitch(l) {\n\t\tcase 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16;\n\t\tcase 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8;\n\t\tcase 1: h ^= (str.charCodeAt(i) & 0xff);\n\t\t\th = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));\n\t}\n\t/* eslint-enable no-fallthrough */\n\th ^= h >>> 13;\n\th = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));\n\th ^= h >>> 15;\n\th = h >>> 0;\n\treturn h;\n}\n\nexport type { SharedMapMemory };"],"names":["DEFAULT_HASH_SIZE","SharedMap","AllocatedMemory","loadPointer","memory","clone","hashMemory","storePointer","key","value","fullHashKey","get32BitHash","maxHash","hashKey","list","pointer","SharedList","listMemory","inserted","data","deleteCurrent","oldMaxHash","newMaxHash","newHashMemory","oldHashMemory","i","hashString","str","l","h","k"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shared-map.js","names":[],"sources":["../src/shared-map.ts"],"sourcesContent":["import AllocatedMemory, { type SharedAllocatedMemory } from './allocated-memory';\nimport type MemoryHeap from './memory-heap';\nimport SharedList from './shared-list';\nimport { loadPointer, storePointer } from './utils/pointer';\n\n// TODO: Grow hashMemory\n// TODO: Add iterator\n// TODO: Add read/write locks\nconst DEFAULT_HASH_SIZE = 10;\nexport default class SharedMap<K extends string | number> {\n\tstatic readonly ALLOCATE_COUNT = 4;\n\n\tprivate memory: MemoryHeap;\n\t// Memory order: Pointer, Lock, Length, MaxHash\n\tprivate pointerMemory: AllocatedMemory;\n\tprivate lock: Int32Array;\n\tprivate get hashMemory(): AllocatedMemory {\n\t\treturn new AllocatedMemory(this.memory, loadPointer(this.pointerMemory.data, 0));\n\t}\n\n\tget length(): number {\n\t\treturn Atomics.load(this.pointerMemory.data, 2);\n\t}\n\tget maxHash(): number {\n\t\treturn Atomics.load(this.pointerMemory.data, 3);\n\t}\n\n\tconstructor(memory: MemoryHeap, clone?: SharedMapMemory) {\n\t\tthis.memory = memory;\n\n\t\tif(clone) {\n\t\t\tthis.pointerMemory = new AllocatedMemory(memory, clone.firstBlock);\n\t\t} else {\n\t\t\tthis.pointerMemory = memory.allocUI32(SharedMap.ALLOCATE_COUNT);\n\t\t\tlet hashMemory = memory.allocUI32(DEFAULT_HASH_SIZE);\n\t\t\tstorePointer(this.pointerMemory.data, 0, hashMemory.bufferPosition, hashMemory.bufferByteOffset);\n\t\t\tAtomics.store(this.pointerMemory.data, 3, DEFAULT_HASH_SIZE);\n\t\t}\n\t\tthis.lock = new Int32Array(this.pointerMemory.data.buffer, this.pointerMemory.bufferByteOffset + Uint32Array.BYTES_PER_ELEMENT, 1);\n\t}\n\n\tset(key: K, value: number) {\n\t\tif(this.length >= this.maxHash * 2) {\n\t\t\tthis.growHashTable();\n\t\t}\n\n\t\tlet fullHashKey = get32BitHash(key);\n\t\tif(this.setHashKey(this.hashMemory, this.maxHash, fullHashKey, value)) {\n\t\t\tAtomics.add(this.pointerMemory.data, 2, 1);\n\t\t}\n\t}\n\tprivate setHashKey(hashMemory: AllocatedMemory, maxHash: number, fullHashKey: number, value: number) {\n\t\tlet hashKey = this.hash(fullHashKey, maxHash);\n\t\t\n\t\tlet list: SharedList;\n\t\tlet pointer = loadPointer(hashMemory.data, hashKey);\n\t\tif(pointer.bufferByteOffset === 0) {\n\t\t\t// Initialize a list here\n\t\t\tlist = new SharedList(this.memory, {\n\t\t\t\tdataLength: 2,\n\t\t\t});\n\n\t\t\tlet listMemory = list.getSharedMemory();\n\t\t\tstorePointer(hashMemory.data, hashKey, listMemory.firstBlock.bufferPosition, listMemory.firstBlock.bufferByteOffset);\n\t\t} else {\n\t\t\tlist = new SharedList(this.memory, {\n\t\t\t\tfirstBlock: pointer,\n\t\t\t});\n\t\t}\n\n\t\t// Check if any other items in list have the same key and delete them\n\t\tlet inserted = true;\n\t\tif(list.deleteValue(fullHashKey)) {\n\t\t\tinserted = false;\n\t\t}\n\t\tlist.insert([fullHashKey, value]);\n\t\t\n\t\treturn inserted;\n\t}\n\n\tget(key: K): number | undefined {\n\t\tlet fullHashKey = get32BitHash(key);\n\t\tlet hashKey = this.hash(fullHashKey, this.maxHash);\n\n\t\tlet pointer = loadPointer(this.hashMemory.data, hashKey);\n\t\tif(pointer.bufferByteOffset === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tlet list = new SharedList(this.memory, {\n\t\t\tfirstBlock: pointer,\n\t\t});\n\n\t\tfor(let { data } of list) {\n\t\t\tif(data[0] === fullHashKey) {\n\t\t\t\treturn data[1];\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n\thas(key: K): boolean {\n\t\tlet fullHashKey = get32BitHash(key);\n\t\tlet hashKey = this.hash(fullHashKey, this.maxHash);\n\n\t\tlet pointer = loadPointer(this.hashMemory.data, hashKey);\n\t\tif(pointer.bufferByteOffset === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tlet list = new SharedList(this.memory, {\n\t\t\tfirstBlock: pointer,\n\t\t});\n\n\t\tfor(let { data } of list) {\n\t\t\tif(data[0] === fullHashKey) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tdelete(key: K): boolean {\n\t\tlet fullHashKey = get32BitHash(key);\n\t\tlet hashKey = this.hash(fullHashKey, this.maxHash);\n\n\t\tlet pointer = loadPointer(this.hashMemory.data, hashKey);\n\t\tif(pointer.bufferByteOffset === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tlet list = new SharedList(this.memory, {\n\t\t\tfirstBlock: pointer,\n\t\t});\n\n\t\tfor(let { data, deleteCurrent } of list) {\n\t\t\tif(data[0] === fullHashKey) {\n\t\t\t\tdeleteCurrent();\n\n\t\t\t\tAtomics.sub(this.pointerMemory.data, 2, 1);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate growHashTable() {\n\t\tlet oldMaxHash = this.maxHash;\n\t\tlet newMaxHash = oldMaxHash * 2;\n\t\tlet newHashMemory = this.memory.allocUI32(newMaxHash);\n\t\tlet oldHashMemory = this.hashMemory;\n\n\t\t// Copy each old hash value into new hash memory\n\t\tfor(let i = 0; i < oldMaxHash; i++) {\n\t\t\tlet pointer = loadPointer(oldHashMemory.data, i);\n\t\t\tif(pointer.bufferByteOffset === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet list = new SharedList(this.memory, {\n\t\t\t\tfirstBlock: pointer,\n\t\t\t});\n\t\t\tfor(let { data } of list) {\n\t\t\t\tthis.setHashKey(newHashMemory, newMaxHash, data[0], data[1]);\n\t\t\t}\n\n\t\t\t// The entries have been copied into freshly allocated lists in the new hash table so the old list can be freed\n\t\t\tlist.free();\n\t\t}\n\n\t\tstorePointer(this.pointerMemory.data, 0, newHashMemory.bufferPosition, newHashMemory.bufferByteOffset);\n\t\tAtomics.store(this.pointerMemory.data, 3, newMaxHash);\n\n\t\t// pointerMemory now references newHashMemory so the old hash table memory can be freed\n\t\toldHashMemory.free();\n\t}\n\n\tprivate hash(key: number, maxHash: number) {\n\t\treturn key % maxHash;\n\t}\n\n\tfree() {\n\t\t// Loop through and free lists in hash table first\n\t\tfor(let i = 0; i < this.maxHash; i++) {\n\t\t\tlet pointer = loadPointer(this.hashMemory.data, i);\n\t\t\tif(pointer.bufferByteOffset === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet list = new SharedList(this.memory, {\n\t\t\t\tfirstBlock: pointer,\n\t\t\t});\n\t\t\tlist.free();\n\t\t}\n\n\t\tthis.hashMemory.free();\n\t\tthis.pointerMemory.free();\n\t}\n\n\tgetSharedMemory(): SharedMapMemory {\n\t\treturn {\n\t\t\tfirstBlock: this.pointerMemory.getSharedMemory(),\n\t\t};\n\t}\n}\n\ninterface SharedMapMemory {\n\tfirstBlock: SharedAllocatedMemory\n}\n\nfunction get32BitHash<K extends string | number>(key: K): number {\n\tif(typeof key === 'number') {\n\t\treturn key;\n\t} else if(typeof key === 'string') {\n\t\treturn hashString(key);\n\t} else {\n\t\treturn key;\n\t}\n}\n\n// Copied from https://github.com/mmomtchev/SharedMap/blob/master/index.js - MurmurHash2\nfunction hashString(str: string): number {\n\tlet\n\t\tl = str.length,\n\t\th = 17 ^ l,\n\t\ti = 0,\n\t\tk;\n\twhile(l >= 4) {\n\t\tk =\n\t\t\t((str.charCodeAt(i) & 0xff)) |\n\t\t\t((str.charCodeAt(++i) & 0xff) << 8) |\n\t\t\t((str.charCodeAt(++i) & 0xff) << 16) |\n\t\t\t((str.charCodeAt(++i) & 0xff) << 14);\n\t\tk = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));\n\t\tk ^= k >>> 14;\n\t\tk = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));\n\t\th = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;\n\t\tl -= 4;\n\t\t++i;\n\t}\n\t/* eslint-disable no-fallthrough */\n\tswitch(l) {\n\t\tcase 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16;\n\t\tcase 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8;\n\t\tcase 1: h ^= (str.charCodeAt(i) & 0xff);\n\t\t\th = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));\n\t}\n\t/* eslint-enable no-fallthrough */\n\th ^= h >>> 13;\n\th = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));\n\th ^= h >>> 15;\n\th = h >>> 0;\n\treturn h;\n}\n\nexport type { SharedMapMemory };"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { SharedListMemory } from './shared-list';
|
|
1
|
+
import AllocatedMemory from './allocated-memory';
|
|
2
|
+
import type MemoryHeap from './memory-heap';
|
|
3
|
+
import type { SharedListMemory } from './shared-list';
|
|
4
4
|
export default abstract class SharedPointerList<T extends PointerItem> implements Iterable<T> {
|
|
5
5
|
private memory;
|
|
6
6
|
private list;
|
|
@@ -1,50 +1,47 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createPointer as e, loadPointer as t } from "./utils/pointer.js";
|
|
2
|
+
import n from "./allocated-memory.js";
|
|
2
3
|
import r from "./shared-list.js";
|
|
3
|
-
|
|
4
|
-
class
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
for (let e of this)
|
|
43
|
-
"free" in e && typeof e.free == "function" ? e.free() : e.memory.free();
|
|
44
|
-
this.list.free();
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
export {
|
|
48
|
-
u as default
|
|
4
|
+
//#region src/shared-pointer-list.ts
|
|
5
|
+
var i = class {
|
|
6
|
+
memory;
|
|
7
|
+
list;
|
|
8
|
+
constructor(e, t) {
|
|
9
|
+
this.memory = e, this.list = t ? new r(e, t) : new r(e);
|
|
10
|
+
}
|
|
11
|
+
get length() {
|
|
12
|
+
return this.list.length;
|
|
13
|
+
}
|
|
14
|
+
insert(t) {
|
|
15
|
+
this.list.insert(e(t.memory.bufferPosition, t.memory.bufferByteOffset));
|
|
16
|
+
}
|
|
17
|
+
delete(t) {
|
|
18
|
+
return this.list.deleteValue(e(t.memory.bufferPosition, t.memory.bufferByteOffset));
|
|
19
|
+
}
|
|
20
|
+
*[Symbol.iterator]() {
|
|
21
|
+
let e = this.list[Symbol.iterator]();
|
|
22
|
+
for (let { data: r } of e) {
|
|
23
|
+
let { bufferPosition: e, bufferByteOffset: i } = t(r, 0), a = new n(this.memory, {
|
|
24
|
+
bufferPosition: e,
|
|
25
|
+
bufferByteOffset: i
|
|
26
|
+
});
|
|
27
|
+
yield this.createItem(a);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
forEach(e) {
|
|
31
|
+
for (let t of this) e(t);
|
|
32
|
+
}
|
|
33
|
+
find(e) {
|
|
34
|
+
for (let t of this) if (e(t)) return t;
|
|
35
|
+
}
|
|
36
|
+
getSharedMemory() {
|
|
37
|
+
return this.list.getSharedMemory();
|
|
38
|
+
}
|
|
39
|
+
free() {
|
|
40
|
+
for (let e of this) "free" in e && typeof e.free == "function" ? e.free() : e.memory.free();
|
|
41
|
+
this.list.free();
|
|
42
|
+
}
|
|
49
43
|
};
|
|
50
|
-
//#
|
|
44
|
+
//#endregion
|
|
45
|
+
export { i as default };
|
|
46
|
+
|
|
47
|
+
//# sourceMappingURL=shared-pointer-list.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-pointer-list.js","sources":["../src/shared-pointer-list.ts"],"sourcesContent":["import AllocatedMemory from './allocated-memory';\nimport type MemoryHeap from './memory-heap';\nimport type { SharedListMemory } from './shared-list';\nimport SharedList from './shared-list';\nimport { createPointer, loadPointer } from './utils/pointer';\n\nexport default abstract class SharedPointerList<T extends PointerItem> implements Iterable<T> {\n\tprivate memory: MemoryHeap;\n\tprivate list: SharedList;\n\n\tconstructor(heap: MemoryHeap, memory?: SharedListMemory) {\n\t\tthis.memory = heap;\n\n\t\tif(memory) {\n\t\t\tthis.list = new SharedList(heap, memory);\n\t\t} else {\n\t\t\tthis.list = new SharedList(heap);\n\t\t}\n\t}\n\n\tget length() {\n\t\treturn this.list.length;\n\t}\n\n\tinsert(item: T) {\n\t\tthis.list.insert(createPointer(item.memory.bufferPosition, item.memory.bufferByteOffset));\n\t}\n\tdelete(item: T) {\n\t\treturn this.list.deleteValue(createPointer(item.memory.bufferPosition, item.memory.bufferByteOffset));\n\t}\n\n\t*[Symbol.iterator]() {\n\t\tlet iterator = this.list[Symbol.iterator]();\n\n\t\tfor(let { data: pointerData } of iterator) {\n\t\t\tlet { bufferPosition, bufferByteOffset } = loadPointer(pointerData, 0);\n\t\t\tlet allocatedMemory = new AllocatedMemory(this.memory, {\n\t\t\t\tbufferPosition,\n\t\t\t\tbufferByteOffset
|
|
1
|
+
{"version":3,"file":"shared-pointer-list.js","names":[],"sources":["../src/shared-pointer-list.ts"],"sourcesContent":["import AllocatedMemory from './allocated-memory';\nimport type MemoryHeap from './memory-heap';\nimport type { SharedListMemory } from './shared-list';\nimport SharedList from './shared-list';\nimport { createPointer, loadPointer } from './utils/pointer';\n\nexport default abstract class SharedPointerList<T extends PointerItem> implements Iterable<T> {\n\tprivate memory: MemoryHeap;\n\tprivate list: SharedList;\n\n\tconstructor(heap: MemoryHeap, memory?: SharedListMemory) {\n\t\tthis.memory = heap;\n\n\t\tif(memory) {\n\t\t\tthis.list = new SharedList(heap, memory);\n\t\t} else {\n\t\t\tthis.list = new SharedList(heap);\n\t\t}\n\t}\n\n\tget length() {\n\t\treturn this.list.length;\n\t}\n\n\tinsert(item: T) {\n\t\tthis.list.insert(createPointer(item.memory.bufferPosition, item.memory.bufferByteOffset));\n\t}\n\tdelete(item: T) {\n\t\treturn this.list.deleteValue(createPointer(item.memory.bufferPosition, item.memory.bufferByteOffset));\n\t}\n\n\t*[Symbol.iterator]() {\n\t\tlet iterator = this.list[Symbol.iterator]();\n\n\t\tfor(let { data: pointerData } of iterator) {\n\t\t\tlet { bufferPosition, bufferByteOffset } = loadPointer(pointerData, 0);\n\t\t\tlet allocatedMemory = new AllocatedMemory(this.memory, {\n\t\t\t\tbufferPosition,\n\t\t\t\tbufferByteOffset,\n\t\t\t});\n\t\t\tyield this.createItem(allocatedMemory);\n\t\t}\n\t}\n\tforEach(callback: (item: T) => void) {\n\t\tfor(let value of this) {\n\t\t\tcallback(value);\n\t\t}\n\t}\n\n\tfind(callback: (item: T) => boolean): T | undefined {\n\t\tfor(let value of this) {\n\t\t\tif(callback(value)) {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\tgetSharedMemory() {\n\t\treturn this.list.getSharedMemory();\n\t}\n\n\tprotected abstract createItem(allocatedMemory: AllocatedMemory): T;\n\n\tfree() {\n\t\tfor(let item of this) {\n\t\t\t// 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\n\t\t\tif('free' in item && typeof item.free === 'function') {\n\t\t\t\titem.free();\n\t\t\t} else {\n\t\t\t\titem.memory.free();\n\t\t\t}\n\t\t}\n\n\t\tthis.list.free();\n\t}\n}\n\ninterface PointerItem {\n\treadonly memory: AllocatedMemory\n}"],"mappings":";;;;AAMA,IAA8B,IAA9B,MAA8F;CAC7F;CACA;CAEA,YAAY,GAAkB,GAA2B;EAGxD,AAFA,KAAK,SAAS,GAEd,AAGC,KAAK,OAHH,IACU,IAAI,EAAW,GAAM,CAAM,IAE3B,IAAI,EAAW,CAAI;CAEjC;CAEA,IAAI,SAAS;EACZ,OAAO,KAAK,KAAK;CAClB;CAEA,OAAO,GAAS;EACf,KAAK,KAAK,OAAO,EAAc,EAAK,OAAO,gBAAgB,EAAK,OAAO,gBAAgB,CAAC;CACzF;CACA,OAAO,GAAS;EACf,OAAO,KAAK,KAAK,YAAY,EAAc,EAAK,OAAO,gBAAgB,EAAK,OAAO,gBAAgB,CAAC;CACrG;CAEA,EAAE,OAAO,YAAY;EACpB,IAAI,IAAW,KAAK,KAAK,OAAO,SAAS,CAAC;EAE1C,KAAI,IAAI,EAAE,MAAM,OAAiB,GAAU;GAC1C,IAAI,EAAE,mBAAgB,wBAAqB,EAAY,GAAa,CAAC,GACjE,IAAkB,IAAI,EAAgB,KAAK,QAAQ;IACtD;IACA;GACD,CAAC;GACD,MAAM,KAAK,WAAW,CAAe;EACtC;CACD;CACA,QAAQ,GAA6B;EACpC,KAAI,IAAI,KAAS,MAChB,EAAS,CAAK;CAEhB;CAEA,KAAK,GAA+C;EACnD,KAAI,IAAI,KAAS,MAChB,IAAG,EAAS,CAAK,GAChB,OAAO;CAKV;CAEA,kBAAkB;EACjB,OAAO,KAAK,KAAK,gBAAgB;CAClC;CAIA,OAAO;EACN,KAAI,IAAI,KAAQ,MAEf,AAAG,UAAU,KAAQ,OAAO,EAAK,QAAS,aACzC,EAAK,KAAK,IAEV,EAAK,OAAO,KAAK;EAInB,KAAK,KAAK,KAAK;CAChB;AACD"}
|
|
@@ -1,14 +1,19 @@
|
|
|
1
|
-
import { SharedAllocatedMemory } from './allocated-memory';
|
|
2
|
-
import { TypedArrayConstructor } from './interfaces/typed-array-constructor';
|
|
3
|
-
import
|
|
1
|
+
import type { SharedAllocatedMemory } from './allocated-memory';
|
|
2
|
+
import type { TypedArrayConstructor } from './interfaces/typed-array-constructor';
|
|
3
|
+
import type MemoryHeap from './memory-heap';
|
|
4
4
|
export default class SharedPool<T extends Uint32Array | Int32Array | Float32Array | Float64Array = Uint32Array> implements Iterable<T> {
|
|
5
|
-
static readonly ALLOCATE_COUNT
|
|
5
|
+
static readonly ALLOCATE_COUNT = 6;
|
|
6
6
|
private memory;
|
|
7
7
|
private firstBlock;
|
|
8
8
|
private uint16Array;
|
|
9
|
-
private
|
|
10
|
-
private
|
|
9
|
+
private growLock;
|
|
10
|
+
private pointerStack;
|
|
11
|
+
private recycleStack;
|
|
11
12
|
private cachedFullDataBlock;
|
|
13
|
+
private readonly cachedMaxChunkSize;
|
|
14
|
+
private readonly cachedDataLength;
|
|
15
|
+
private readonly cachedType;
|
|
16
|
+
private readonly cachedByteMultipler;
|
|
12
17
|
get length(): number;
|
|
13
18
|
get maxChunkSize(): number;
|
|
14
19
|
private set maxChunkSize(value);
|
|
@@ -17,7 +22,6 @@ export default class SharedPool<T extends Uint32Array | Int32Array | Float32Arra
|
|
|
17
22
|
get dataLength(): number;
|
|
18
23
|
private set dataLength(value);
|
|
19
24
|
get bufferLength(): number;
|
|
20
|
-
get recycleBufferLength(): number;
|
|
21
25
|
get byteMultipler(): number;
|
|
22
26
|
constructor(memory: MemoryHeap, config?: SharedPoolConfig<T> | SharedPoolMemory);
|
|
23
27
|
at(index: number): T;
|
|
@@ -35,7 +39,6 @@ interface SharedPoolConfig<T extends Uint32Array | Int32Array | Float32Array | F
|
|
|
35
39
|
maxChunkSize?: number;
|
|
36
40
|
type?: TypedArrayConstructor<T>;
|
|
37
41
|
dataLength?: number;
|
|
38
|
-
recycleBufferLength?: number;
|
|
39
42
|
}
|
|
40
43
|
interface SharedPoolMemory {
|
|
41
44
|
firstBlock: SharedAllocatedMemory;
|
package/dist/shared-pool.js
CHANGED
|
@@ -1,165 +1,145 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
return this.cachedFullDataBlock[e] = a, a;
|
|
143
|
-
}
|
|
144
|
-
getDataBlock(t, e) {
|
|
145
|
-
const i = e * this.dataLength;
|
|
146
|
-
return t.subarray(i, i + this.dataLength);
|
|
147
|
-
}
|
|
148
|
-
free() {
|
|
149
|
-
this.recycleVector.free();
|
|
150
|
-
for (let t of this.pointerVector) {
|
|
151
|
-
let e = t[0];
|
|
152
|
-
new f(this.memory, n(e)).free();
|
|
153
|
-
}
|
|
154
|
-
this.pointerVector.free(), this.firstBlock.free();
|
|
155
|
-
}
|
|
156
|
-
getSharedMemory() {
|
|
157
|
-
return {
|
|
158
|
-
firstBlock: this.firstBlock.getSharedMemory()
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
export {
|
|
163
|
-
k as default
|
|
1
|
+
import { getPointer as e, loadRawPointer as t, storeRawPointer as n } from "./utils/pointer.js";
|
|
2
|
+
import r from "./allocated-memory.js";
|
|
3
|
+
import { lock as i, unlock as a } from "./lock/simple-lock.js";
|
|
4
|
+
import o from "./shared-stack.js";
|
|
5
|
+
//#region src/shared-pool.ts
|
|
6
|
+
var s = 0, c = 1, l = 2, u = 3, d = 4, f = 5, p = class p {
|
|
7
|
+
static ALLOCATE_COUNT = 6;
|
|
8
|
+
memory;
|
|
9
|
+
firstBlock;
|
|
10
|
+
uint16Array;
|
|
11
|
+
growLock;
|
|
12
|
+
pointerStack;
|
|
13
|
+
recycleStack;
|
|
14
|
+
cachedFullDataBlock = {};
|
|
15
|
+
cachedMaxChunkSize;
|
|
16
|
+
cachedDataLength;
|
|
17
|
+
cachedType;
|
|
18
|
+
cachedByteMultipler;
|
|
19
|
+
get length() {
|
|
20
|
+
return Atomics.load(this.firstBlock.data, s) - this.recycleStack.length;
|
|
21
|
+
}
|
|
22
|
+
get maxChunkSize() {
|
|
23
|
+
return this.cachedMaxChunkSize;
|
|
24
|
+
}
|
|
25
|
+
set maxChunkSize(e) {
|
|
26
|
+
Atomics.store(this.firstBlock.data, l, e);
|
|
27
|
+
}
|
|
28
|
+
get type() {
|
|
29
|
+
return this.cachedType;
|
|
30
|
+
}
|
|
31
|
+
set type(e) {
|
|
32
|
+
Atomics.store(this.uint16Array, 0, e);
|
|
33
|
+
}
|
|
34
|
+
get dataLength() {
|
|
35
|
+
return this.cachedDataLength;
|
|
36
|
+
}
|
|
37
|
+
set dataLength(e) {
|
|
38
|
+
Atomics.store(this.uint16Array, 1, e);
|
|
39
|
+
}
|
|
40
|
+
get bufferLength() {
|
|
41
|
+
return this.cachedMaxChunkSize * this.pointerStack.length;
|
|
42
|
+
}
|
|
43
|
+
get byteMultipler() {
|
|
44
|
+
return this.cachedByteMultipler;
|
|
45
|
+
}
|
|
46
|
+
constructor(i, a) {
|
|
47
|
+
if (this.memory = i, a && "firstBlock" in a) this.firstBlock = new r(i, a.firstBlock), this.uint16Array = new Uint16Array(this.firstBlock.data.buffer, this.firstBlock.bufferByteOffset + c * Uint32Array.BYTES_PER_ELEMENT, 2), this.pointerStack = new o(i, { firstBlock: e(t(this.firstBlock.data, d)) }), this.recycleStack = new o(i, { firstBlock: e(t(this.firstBlock.data, f)) });
|
|
48
|
+
else {
|
|
49
|
+
this.firstBlock = i.allocUI32(p.ALLOCATE_COUNT + o.DEFAULT_ALLOCATE_COUNT * 2), this.uint16Array = new Uint16Array(this.firstBlock.data.buffer, this.firstBlock.bufferByteOffset + c * Uint32Array.BYTES_PER_ELEMENT, 2);
|
|
50
|
+
let e = a?.dataLength ?? 1, t = a?.maxChunkSize ?? 100;
|
|
51
|
+
this.pointerStack = new o(i, {
|
|
52
|
+
firstBlock: this.firstBlock.getSubAllocation(p.ALLOCATE_COUNT, o.DEFAULT_ALLOCATE_COUNT),
|
|
53
|
+
type: Uint32Array
|
|
54
|
+
}), n(this.firstBlock.data, d, this.pointerStack.pointer), this.recycleStack = new o(i, {
|
|
55
|
+
firstBlock: this.firstBlock.getSubAllocation(p.ALLOCATE_COUNT + o.DEFAULT_ALLOCATE_COUNT, o.DEFAULT_ALLOCATE_COUNT),
|
|
56
|
+
type: Uint32Array
|
|
57
|
+
}), n(this.firstBlock.data, f, this.recycleStack.pointer);
|
|
58
|
+
let r = a?.type ?? Uint32Array;
|
|
59
|
+
r === Uint32Array ? this.type = 0 : r === Int32Array ? this.type = 1 : r === Float32Array ? this.type = 2 : r === Float64Array && (this.type = 3), this.dataLength = e, this.maxChunkSize = t;
|
|
60
|
+
let s = r === Float64Array ? 2 : 1, l = i.allocUI32(t * e * s);
|
|
61
|
+
this.pointerStack.push(l.pointer);
|
|
62
|
+
}
|
|
63
|
+
this.cachedType = this.uint16Array[0], this.cachedDataLength = Math.max(1, this.uint16Array[1]), this.cachedMaxChunkSize = this.firstBlock.data[l], this.cachedByteMultipler = this.cachedType === 3 ? 2 : 1, this.growLock = new Int32Array(this.firstBlock.data.buffer, this.firstBlock.bufferByteOffset + u * Uint32Array.BYTES_PER_ELEMENT, 1);
|
|
64
|
+
}
|
|
65
|
+
at(e) {
|
|
66
|
+
let t = this.getFullDataBlock(e);
|
|
67
|
+
return this.getDataBlock(t, e % this.cachedMaxChunkSize);
|
|
68
|
+
}
|
|
69
|
+
get(e, t = 0) {
|
|
70
|
+
let n = this.cachedDataLength;
|
|
71
|
+
if (t >= n) throw Error(`${t} is out of dataLength bounds ${n}`);
|
|
72
|
+
return this.getFullDataBlock(e)[e % this.cachedMaxChunkSize * n + t];
|
|
73
|
+
}
|
|
74
|
+
push(e) {
|
|
75
|
+
let t = this.cachedDataLength, n = typeof e == "number";
|
|
76
|
+
if (!n && e.length > t) throw Error(`Can't insert ${e.length} array into shared list of ${t} dataLength`);
|
|
77
|
+
let r = this.recycleStack.pop();
|
|
78
|
+
r === void 0 && (r = Atomics.add(this.firstBlock.data, s, 1));
|
|
79
|
+
let i = this.getFullDataBlock(r), a = t * (r % this.cachedMaxChunkSize);
|
|
80
|
+
return n ? i[a] = e : i.set(e, a), r;
|
|
81
|
+
}
|
|
82
|
+
deleteIndex(e) {
|
|
83
|
+
this.recycleStack.push(e);
|
|
84
|
+
}
|
|
85
|
+
clear() {
|
|
86
|
+
this.firstBlock.data[s] = 0, this.recycleStack.clear();
|
|
87
|
+
}
|
|
88
|
+
*[Symbol.iterator]() {
|
|
89
|
+
let e = {};
|
|
90
|
+
for (let t of this.recycleStack) e[t] = !0;
|
|
91
|
+
let t = this.cachedMaxChunkSize, n = Atomics.load(this.firstBlock.data, s), r = this.getFullDataBlock(0), i = 0;
|
|
92
|
+
for (let a = 0; a < n; a++) if (!e[a]) {
|
|
93
|
+
let e = Math.floor(a / t);
|
|
94
|
+
e !== i && (r = this.getFullDataBlock(a), i = e), yield this.getDataBlock(r, a % t);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
getFullDataBlock(t) {
|
|
98
|
+
let n = Math.floor(t / this.cachedMaxChunkSize), o = this.cachedFullDataBlock[n];
|
|
99
|
+
if (o) return o;
|
|
100
|
+
if (n >= this.pointerStack.length) {
|
|
101
|
+
i(this.growLock);
|
|
102
|
+
try {
|
|
103
|
+
for (; n >= this.pointerStack.length;) {
|
|
104
|
+
let e = this.memory.allocUI32(this.cachedMaxChunkSize * this.cachedDataLength * this.cachedByteMultipler);
|
|
105
|
+
this.pointerStack.push(e.pointer);
|
|
106
|
+
}
|
|
107
|
+
} finally {
|
|
108
|
+
a(this.growLock);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
let s = new r(this.memory, e(this.pointerStack.at(n))), c = this.cachedDataLength * this.cachedMaxChunkSize, l;
|
|
112
|
+
switch (this.cachedType) {
|
|
113
|
+
case 1:
|
|
114
|
+
l = new Int32Array(s.data.buffer, s.bufferByteOffset, c);
|
|
115
|
+
break;
|
|
116
|
+
case 0:
|
|
117
|
+
l = new Uint32Array(s.data.buffer, s.bufferByteOffset, c);
|
|
118
|
+
break;
|
|
119
|
+
case 2:
|
|
120
|
+
l = new Float32Array(s.data.buffer, s.bufferByteOffset, c);
|
|
121
|
+
break;
|
|
122
|
+
case 3:
|
|
123
|
+
l = new Float64Array(s.data.buffer, s.bufferByteOffset, c);
|
|
124
|
+
break;
|
|
125
|
+
default: throw Error(`Unknown data block type ${this.cachedType}`);
|
|
126
|
+
}
|
|
127
|
+
return this.cachedFullDataBlock[n] = l, l;
|
|
128
|
+
}
|
|
129
|
+
getDataBlock(e, t) {
|
|
130
|
+
let n = this.cachedDataLength, r = t * n;
|
|
131
|
+
return e.subarray(r, r + n);
|
|
132
|
+
}
|
|
133
|
+
free() {
|
|
134
|
+
this.recycleStack.free();
|
|
135
|
+
for (let t of this.pointerStack) new r(this.memory, e(t)).free();
|
|
136
|
+
this.pointerStack.free(), this.firstBlock.free();
|
|
137
|
+
}
|
|
138
|
+
getSharedMemory() {
|
|
139
|
+
return { firstBlock: this.firstBlock.getSharedMemory() };
|
|
140
|
+
}
|
|
164
141
|
};
|
|
165
|
-
//#
|
|
142
|
+
//#endregion
|
|
143
|
+
export { p as default };
|
|
144
|
+
|
|
145
|
+
//# sourceMappingURL=shared-pool.js.map
|
package/dist/shared-pool.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-pool.js","sources":["../src/shared-pool.ts"],"sourcesContent":["import type { SharedAllocatedMemory } from './allocated-memory';\nimport AllocatedMemory from './allocated-memory';\nimport type { TypedArrayConstructor } from './interfaces/typed-array-constructor';\nimport type MemoryHeap from './memory-heap';\nimport SharedVector from './shared-vector';\nimport { getPointer } from './utils/pointer';\n\nenum TYPE {\n\tuint32,\n\tint32,\n\tfloat32,\n\tfloat64\n}\n\nconst LENGTH_INDEX = 0;\nconst TYPE_INDEX = 1;\nconst MAX_CHUNK_SIZE_INDEX = 2;\nconst POINTERS_INDEX = 3;\nconst RECYCLE_INDEX = POINTERS_INDEX + SharedVector.ALLOCATE_COUNT;\n\n// Array with stable indexes and maximum contiguous memory sizes (necessary to fit large data sets into max 1MB buffers)\n// https://plflib.org/colony.htm for future enhancements - it seems to be an optimized version of what we were aiming for with this\nexport default class SharedPool<T extends Uint32Array | Int32Array | Float32Array | Float64Array = Uint32Array> implements Iterable<T> {\n\tstatic readonly ALLOCATE_COUNT = 3 + SharedVector.ALLOCATE_COUNT * 2;\n\tprivate memory: MemoryHeap;\n\n\t// Current Length, Type/DataLength, MaxChunkLength, Pointer vector, Recycle vector\n\tprivate firstBlock: AllocatedMemory;\n\tprivate uint16Array: Uint16Array;\n\tprivate pointerVector: SharedVector<Uint32Array>;\n\tprivate recycleVector: SharedVector<Uint32Array>;\n\n\tprivate cachedFullDataBlock: { [key: number]: T } = {};\n\n\tget length(): number {\n\t\treturn Atomics.load(this.firstBlock.data, LENGTH_INDEX) - this.recycleVector.length;\n\t}\n\tget maxChunkSize(): number {\n\t\treturn this.firstBlock.data[MAX_CHUNK_SIZE_INDEX];\n\t}\n\tprivate set maxChunkSize(value: number) {\n\t\tAtomics.store(this.firstBlock.data, MAX_CHUNK_SIZE_INDEX, value);\n\t}\n\t\n\tget type(): number {\n\t\treturn this.uint16Array[0];\n\t}\n\tprivate set type(value: number) {\n\t\tAtomics.store(this.uint16Array, 0, value);\n\t}\n\tget dataLength(): number {\n\t\treturn Math.max(1, this.uint16Array[1]);\n\t}\n\tprivate set dataLength(value: number) {\n\t\tAtomics.store(this.uint16Array, 1, value);\n\t}\n\n\tget bufferLength(): number {\n\t\treturn this.maxChunkSize * this.pointerVector.length;\n\t}\n\tget recycleBufferLength(): number {\n\t\treturn this.recycleVector.bufferLength;\n\t}\n\tget byteMultipler(): number {\n\t\tif(this.type === TYPE.float64) {\n\t\t\treturn 2;\n\t\t} else {\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\tconstructor(memory: MemoryHeap, config?: SharedPoolConfig<T> | SharedPoolMemory) {\n\t\tthis.memory = memory;\n\n\t\tif(config && 'firstBlock' in config) {\n\t\t\tthis.firstBlock = new AllocatedMemory(memory, config.firstBlock);\n\t\t\tthis.uint16Array = new Uint16Array(this.firstBlock.data.buffer, this.firstBlock.bufferByteOffset + TYPE_INDEX * Uint32Array.BYTES_PER_ELEMENT, 2);\n\t\t\tthis.pointerVector = new SharedVector(memory, {\n\t\t\t\tfirstBlock: {\n\t\t\t\t\tbufferPosition: this.firstBlock.bufferPosition,\n\t\t\t\t\tbufferByteOffset: this.firstBlock.bufferByteOffset + POINTERS_INDEX * Uint32Array.BYTES_PER_ELEMENT\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis.recycleVector = new SharedVector(memory, {\n\t\t\t\tfirstBlock: {\n\t\t\t\t\tbufferPosition: this.firstBlock.bufferPosition,\n\t\t\t\t\tbufferByteOffset: this.firstBlock.bufferByteOffset + RECYCLE_INDEX * Uint32Array.BYTES_PER_ELEMENT\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tthis.firstBlock = memory.allocUI32(SharedPool.ALLOCATE_COUNT);\n\t\t\tthis.uint16Array = new Uint16Array(this.firstBlock.data.buffer, this.firstBlock.bufferByteOffset + TYPE_INDEX * Uint32Array.BYTES_PER_ELEMENT, 2);\n\n\t\t\tlet dataLength = config?.dataLength ?? 1;\n\t\t\tlet maxLength = config?.maxChunkSize ?? 100;\n\n\t\t\tthis.pointerVector = new SharedVector(memory, {\n\t\t\t\ttype: Uint32Array,\n\t\t\t\tfirstBlock: {\n\t\t\t\t\tbufferPosition: this.firstBlock.bufferPosition,\n\t\t\t\t\tbufferByteOffset: this.firstBlock.bufferByteOffset + POINTERS_INDEX * Uint32Array.BYTES_PER_ELEMENT\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis.recycleVector = new SharedVector(memory, {\n\t\t\t\ttype: Uint32Array,\n\t\t\t\tfirstBlock: {\n\t\t\t\t\tbufferPosition: this.firstBlock.bufferPosition,\n\t\t\t\t\tbufferByteOffset: this.firstBlock.bufferByteOffset + RECYCLE_INDEX * Uint32Array.BYTES_PER_ELEMENT\n\t\t\t\t},\n\t\t\t\tbufferLength: config?.recycleBufferLength\n\t\t\t});\n\n\t\t\tconst type = config?.type ?? Uint32Array;\n\t\t\tif(type === Uint32Array) {\n\t\t\t\tthis.type = TYPE.uint32;\n\t\t\t}\n\t\t\t// @ts-expect-error\n\t\t\telse if(type === Int32Array) {\n\t\t\t\tthis.type = TYPE.int32;\n\t\t\t}\n\t\t\t// @ts-expect-error\n\t\t\telse if(type === Float32Array) {\n\t\t\t\tthis.type = TYPE.float32;\n\t\t\t// @ts-expect-error\n\t\t\t} else if(type === Float64Array) {\n\t\t\t\tthis.type = TYPE.float64;\n\t\t\t}\n\t\t\tthis.dataLength = dataLength;\n\t\t\tthis.maxChunkSize = maxLength;\n\n\t\t\tlet firstArray = memory.allocUI32(maxLength * dataLength * this.byteMultipler);\n\t\t\tthis.pointerVector.push(firstArray.pointer);\n\t\t}\n\t}\n\n\tat(index: number): T {\n\t\tlet dataBlock = this.getFullDataBlock(index);\n\t\treturn this.getDataBlock(dataBlock, index % this.maxChunkSize);\n\t}\n\tget(index: number, dataIndex = 0): number {\n\t\tconst dataLength = this.dataLength;\n\t\tif(dataIndex >= dataLength) {\n\t\t\tthrow new Error(`${dataIndex} is out of dataLength bounds ${dataLength}`);\n\t\t}\n\n\t\tlet dataBlock = this.getFullDataBlock(index);\n\t\treturn dataBlock[(index % this.maxChunkSize) * dataLength + dataIndex];\n\t}\n\n\tpush(values: number | Array<number>): number {\n\t\tif(typeof values === 'number') {\n\t\t\tvalues = [values];\n\t\t}\n\n\t\tlet dataLength = this.dataLength;\n\t\tif(values.length > dataLength) {\n\t\t\tthrow new Error(`Can't insert ${values.length} array into shared list of ${dataLength} dataLength`);\n\t\t}\n\n\t\tlet newIndex;\n\t\tif(this.recycleVector.length) {\n\t\t\tnewIndex = this.recycleVector.popNumber();\n\t\t} else {\n\t\t\tnewIndex = Atomics.add(this.firstBlock.data, LENGTH_INDEX, 1);\n\t\t}\n\t\t\n\t\tlet dataBlock = this.getFullDataBlock(newIndex);\n\t\tlet blockIndex = newIndex % this.maxChunkSize;\n\t\tdataBlock.set(values, dataLength * blockIndex);\n\n\t\treturn newIndex;\n\t}\n\n\tdeleteIndex(index: number) {\n\t\tthis.recycleVector.push(index);\n\t}\n\n\tclear() {\n\t\tthis.firstBlock.data[LENGTH_INDEX] = 0;\n\t\tthis.recycleVector.clear();\n\t}\n\n\t*[Symbol.iterator]() {\n\t\tconst recycledValues: { [key: number]: true } = {};\n\t\tfor(let value of this.recycleVector) {\n\t\t\trecycledValues[value[0]] = true;\n\t\t}\n\n\t\tlet dataBlock = this.getFullDataBlock(0);\n\t\tlet dataBlockIndex = 0;\n\t\tfor(let i = 0; i < Atomics.load(this.firstBlock.data, LENGTH_INDEX); i++) {\n\t\t\tif(!recycledValues[i]) {\n\t\t\t\tlet newDataBlockIndex = Math.floor(i / this.maxChunkSize);\n\t\t\t\tif(newDataBlockIndex !== dataBlockIndex) {\n\t\t\t\t\tdataBlock = this.getFullDataBlock(i);\n\t\t\t\t\tdataBlockIndex = newDataBlockIndex;\n\t\t\t\t}\n\t\t\t\tyield this.getDataBlock(dataBlock, i % this.maxChunkSize);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate getFullDataBlock(index: number) {\n\t\tlet pointerIndex = Math.floor(index / this.maxChunkSize);\n\t\tlet cachedDataBlock = this.cachedFullDataBlock[pointerIndex];\n\t\tif(cachedDataBlock) {\n\t\t\treturn cachedDataBlock;\n\t\t}\n\t\tif(pointerIndex >= this.pointerVector.length) {\n\t\t\tlet newArray = this.memory.allocUI32(this.maxChunkSize * this.dataLength * this.byteMultipler);\n\t\t\tthis.pointerVector.push(newArray.pointer);\n\t\t}\n\n\t\tlet array = new AllocatedMemory(this.memory, getPointer(this.pointerVector.get(pointerIndex)));\n\n\t\tlet data: T;\n\t\tswitch(this.type) {\n\t\t\tcase TYPE.int32:\n\t\t\t\tdata = new Int32Array(array.data.buffer, array.bufferByteOffset, this.dataLength * this.maxChunkSize) as T;\n\t\t\t\tbreak;\n\t\t\tcase TYPE.uint32:\n\t\t\t\tdata = new Uint32Array(array.data.buffer, array.bufferByteOffset, this.dataLength * this.maxChunkSize) as T;\n\t\t\t\tbreak;\n\t\t\tcase TYPE.float32:\n\t\t\t\tdata = new Float32Array(array.data.buffer, array.bufferByteOffset, this.dataLength * this.maxChunkSize) as T;\n\t\t\t\tbreak;\n\t\t\tcase TYPE.float64:\n\t\t\t\tdata = new Float64Array(array.data.buffer, array.bufferByteOffset, this.dataLength * this.maxChunkSize) as T;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unknown data block type ${this.type}`);\n\t\t}\n\n\t\tthis.cachedFullDataBlock[pointerIndex] = data;\n\t\treturn data;\n\t}\n\n\tprivate getDataBlock(rawData: T, index: number): T {\n\t\tconst start = index * this.dataLength;\n\t\treturn rawData.subarray(start, start + this.dataLength) as T;\n\t}\n\n\tfree() {\n\t\tthis.recycleVector.free();\n\n\t\tfor(let pointerArray of this.pointerVector) {\n\t\t\tlet pointer = pointerArray[0];\n\t\t\tlet memory = new AllocatedMemory(this.memory, getPointer(pointer));\n\t\t\tmemory.free();\n\t\t}\n\t\tthis.pointerVector.free();\n\t\tthis.firstBlock.free();\n\t}\n\n\tgetSharedMemory(): SharedPoolMemory {\n\t\treturn {\n\t\t\tfirstBlock: this.firstBlock.getSharedMemory()\n\t\t};\n\t}\n}\n\ninterface SharedPoolConfig<T extends Uint32Array | Int32Array | Float32Array | Float64Array> {\n\tmaxChunkSize?: number\n\ttype?: TypedArrayConstructor<T>\n\tdataLength?: number\n\trecycleBufferLength?: number\n}\ninterface SharedPoolMemory {\n\tfirstBlock: SharedAllocatedMemory\n}\n\nexport type { SharedPoolConfig, SharedPoolMemory };"],"names":["LENGTH_INDEX","TYPE_INDEX","MAX_CHUNK_SIZE_INDEX","POINTERS_INDEX","RECYCLE_INDEX","SharedVector","SharedPool","value","memory","config","AllocatedMemory","dataLength","maxLength","type","firstArray","index","dataBlock","dataIndex","values","newIndex","blockIndex","recycledValues","dataBlockIndex","i","newDataBlockIndex","pointerIndex","cachedDataBlock","newArray","array","getPointer","data","rawData","start","pointerArray","pointer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shared-pool.js","names":[],"sources":["../src/shared-pool.ts"],"sourcesContent":["import type { SharedAllocatedMemory } from './allocated-memory';\nimport AllocatedMemory from './allocated-memory';\nimport type { TypedArrayConstructor } from './interfaces/typed-array-constructor';\nimport { lock, unlock } from './lock/simple-lock';\nimport type MemoryHeap from './memory-heap';\nimport SharedStack from './shared-stack';\nimport { getPointer, loadRawPointer, storeRawPointer } from './utils/pointer';\n\nenum TYPE {\n\tuint32,\n\tint32,\n\tfloat32,\n\tfloat64,\n}\n\nconst LENGTH_INDEX = 0;\nconst TYPE_INDEX = 1;\nconst MAX_CHUNK_SIZE_INDEX = 2;\n// Guards appending a chunk pointer so only one thread grows the pointer stack at a time\nconst GROW_LOCK_INDEX = 3;\n// Pointers to the two backing SharedStacks (their own firstBlocks): the chunk pointers and the recycled indexes\nconst POINTER_STACK_INDEX = 4;\nconst RECYCLE_STACK_INDEX = 5;\n\n// Array with stable indexes and maximum contiguous memory sizes (necessary to fit large data sets into max 1MB buffers).\n// The chunk pointers and the recycled indexes both live in SharedStacks, whose segments are never moved or freed once\n// published, so concurrent readers never touch memory that is being reclaimed.\n// https://plflib.org/colony.htm for future enhancements - it seems to be an optimized version of what we were aiming for with this\nexport default class SharedPool<T extends Uint32Array | Int32Array | Float32Array | Float64Array = Uint32Array> implements Iterable<T> {\n\tstatic readonly ALLOCATE_COUNT = 6;\n\tprivate memory: MemoryHeap;\n\n\t// Current Length, Type/DataLength, MaxChunkLength, Grow lock, Pointer stack, Recycle stack\n\tprivate firstBlock: AllocatedMemory;\n\tprivate uint16Array: Uint16Array;\n\tprivate growLock: Int32Array;\n\tprivate pointerStack: SharedStack;\n\tprivate recycleStack: SharedStack;\n\n\tprivate cachedFullDataBlock: { [key: number]: T } = {};\n\n\t// Config is written once at construction and never mutated, so it is cached in plain fields\n\tprivate readonly cachedMaxChunkSize: number;\n\tprivate readonly cachedDataLength: number;\n\tprivate readonly cachedType: number;\n\tprivate readonly cachedByteMultipler: number;\n\n\tget length(): number {\n\t\treturn Atomics.load(this.firstBlock.data, LENGTH_INDEX) - this.recycleStack.length;\n\t}\n\tget maxChunkSize(): number {\n\t\treturn this.cachedMaxChunkSize;\n\t}\n\tprivate set maxChunkSize(value: number) {\n\t\tAtomics.store(this.firstBlock.data, MAX_CHUNK_SIZE_INDEX, value);\n\t}\n\n\tget type(): number {\n\t\treturn this.cachedType;\n\t}\n\tprivate set type(value: number) {\n\t\tAtomics.store(this.uint16Array, 0, value);\n\t}\n\tget dataLength(): number {\n\t\treturn this.cachedDataLength;\n\t}\n\tprivate set dataLength(value: number) {\n\t\tAtomics.store(this.uint16Array, 1, value);\n\t}\n\n\tget bufferLength(): number {\n\t\treturn this.cachedMaxChunkSize * this.pointerStack.length;\n\t}\n\tget byteMultipler(): number {\n\t\treturn this.cachedByteMultipler;\n\t}\n\n\tconstructor(memory: MemoryHeap, config?: SharedPoolConfig<T> | SharedPoolMemory) {\n\t\tthis.memory = memory;\n\n\t\tif(config && 'firstBlock' in config) {\n\t\t\tthis.firstBlock = new AllocatedMemory(memory, config.firstBlock);\n\t\t\tthis.uint16Array = new Uint16Array(this.firstBlock.data.buffer, this.firstBlock.bufferByteOffset + TYPE_INDEX * Uint32Array.BYTES_PER_ELEMENT, 2);\n\t\t\tthis.pointerStack = new SharedStack(memory, {\n\t\t\t\tfirstBlock: getPointer(loadRawPointer(this.firstBlock.data, POINTER_STACK_INDEX)),\n\t\t\t});\n\t\t\tthis.recycleStack = new SharedStack(memory, {\n\t\t\t\tfirstBlock: getPointer(loadRawPointer(this.firstBlock.data, RECYCLE_STACK_INDEX)),\n\t\t\t});\n\t\t} else {\n\t\t\t// Inline both stacks' firstBlocks right after the pool header so the whole spine is one contiguous allocation\n\t\t\tthis.firstBlock = memory.allocUI32(SharedPool.ALLOCATE_COUNT + SharedStack.DEFAULT_ALLOCATE_COUNT * 2);\n\t\t\tthis.uint16Array = new Uint16Array(this.firstBlock.data.buffer, this.firstBlock.bufferByteOffset + TYPE_INDEX * Uint32Array.BYTES_PER_ELEMENT, 2);\n\n\t\t\tlet dataLength = config?.dataLength ?? 1;\n\t\t\tlet maxLength = config?.maxChunkSize ?? 100;\n\n\t\t\tthis.pointerStack = new SharedStack(memory, {\n\t\t\t\tfirstBlock: this.firstBlock.getSubAllocation(SharedPool.ALLOCATE_COUNT, SharedStack.DEFAULT_ALLOCATE_COUNT),\n\t\t\t\ttype: Uint32Array,\n\t\t\t});\n\t\t\tstoreRawPointer(this.firstBlock.data, POINTER_STACK_INDEX, this.pointerStack.pointer);\n\t\t\tthis.recycleStack = new SharedStack(memory, {\n\t\t\t\tfirstBlock: this.firstBlock.getSubAllocation(SharedPool.ALLOCATE_COUNT + SharedStack.DEFAULT_ALLOCATE_COUNT, SharedStack.DEFAULT_ALLOCATE_COUNT),\n\t\t\t\ttype: Uint32Array,\n\t\t\t});\n\t\t\tstoreRawPointer(this.firstBlock.data, RECYCLE_STACK_INDEX, this.recycleStack.pointer);\n\n\t\t\tconst type = config?.type ?? Uint32Array;\n\t\t\tif(type === Uint32Array) {\n\t\t\t\tthis.type = TYPE.uint32;\n\t\t\t// @ts-expect-error\n\t\t\t} else if(type === Int32Array) {\n\t\t\t\tthis.type = TYPE.int32;\n\t\t\t// @ts-expect-error\n\t\t\t} else if(type === Float32Array) {\n\t\t\t\tthis.type = TYPE.float32;\n\t\t\t// @ts-expect-error\n\t\t\t} else if(type === Float64Array) {\n\t\t\t\tthis.type = TYPE.float64;\n\t\t\t}\n\t\t\tthis.dataLength = dataLength;\n\t\t\tthis.maxChunkSize = maxLength;\n\n\t\t\t// @ts-expect-error\n\t\t\tlet byteMultipler = type === Float64Array ? 2 : 1;\n\t\t\tlet firstArray = memory.allocUI32(maxLength * dataLength * byteMultipler);\n\t\t\tthis.pointerStack.push(firstArray.pointer);\n\t\t}\n\n\t\tthis.cachedType = this.uint16Array[0];\n\t\tthis.cachedDataLength = Math.max(1, this.uint16Array[1]);\n\t\tthis.cachedMaxChunkSize = this.firstBlock.data[MAX_CHUNK_SIZE_INDEX];\n\t\tthis.cachedByteMultipler = this.cachedType === TYPE.float64 ? 2 : 1;\n\n\t\tthis.growLock = new Int32Array(this.firstBlock.data.buffer, this.firstBlock.bufferByteOffset + GROW_LOCK_INDEX * Uint32Array.BYTES_PER_ELEMENT, 1);\n\t}\n\n\tat(index: number): T {\n\t\tlet dataBlock = this.getFullDataBlock(index);\n\t\treturn this.getDataBlock(dataBlock, index % this.cachedMaxChunkSize);\n\t}\n\tget(index: number, dataIndex = 0): number {\n\t\tconst dataLength = this.cachedDataLength;\n\t\tif(dataIndex >= dataLength) {\n\t\t\tthrow new Error(`${dataIndex} is out of dataLength bounds ${dataLength}`);\n\t\t}\n\n\t\tlet dataBlock = this.getFullDataBlock(index);\n\t\treturn dataBlock[(index % this.cachedMaxChunkSize) * dataLength + dataIndex];\n\t}\n\n\tpush(values: number | Array<number>): number {\n\t\tlet dataLength = this.cachedDataLength;\n\t\tconst isSingleNumber = typeof values === 'number';\n\t\tif(!isSingleNumber && values.length > dataLength) {\n\t\t\tthrow new Error(`Can't insert ${values.length} array into shared list of ${dataLength} dataLength`);\n\t\t}\n\n\t\t// Reuse a recycled index if one is available. pop() can come back undefined when another thread drained the last\n\t\t// slot between our two calls, so fall through to a fresh index rather than trusting a length() read\n\t\tlet newIndex = this.recycleStack.pop();\n\t\tif(newIndex === undefined) {\n\t\t\tnewIndex = Atomics.add(this.firstBlock.data, LENGTH_INDEX, 1);\n\t\t}\n\n\t\tlet dataBlock = this.getFullDataBlock(newIndex);\n\t\tlet startIndex = dataLength * (newIndex % this.cachedMaxChunkSize);\n\t\tif(isSingleNumber) {\n\t\t\tdataBlock[startIndex] = values;\n\t\t} else {\n\t\t\tdataBlock.set(values, startIndex);\n\t\t}\n\n\t\treturn newIndex;\n\t}\n\n\tdeleteIndex(index: number) {\n\t\tthis.recycleStack.push(index);\n\t}\n\n\tclear() {\n\t\tthis.firstBlock.data[LENGTH_INDEX] = 0;\n\t\tthis.recycleStack.clear();\n\t}\n\n\t*[Symbol.iterator]() {\n\t\tconst recycledValues: { [key: number]: true } = {};\n\t\tfor(let value of this.recycleStack) {\n\t\t\trecycledValues[value] = true;\n\t\t}\n\n\t\tconst maxChunkSize = this.cachedMaxChunkSize;\n\t\t// Snapshot the length once - iteration over a concurrently mutated pool is a snapshot anyway, and re-loading the\n\t\t// atomic every step is pure overhead\n\t\tconst length = Atomics.load(this.firstBlock.data, LENGTH_INDEX);\n\t\tlet dataBlock = this.getFullDataBlock(0);\n\t\tlet dataBlockIndex = 0;\n\t\tfor(let i = 0; i < length; i++) {\n\t\t\tif(!recycledValues[i]) {\n\t\t\t\tlet newDataBlockIndex = Math.floor(i / maxChunkSize);\n\t\t\t\tif(newDataBlockIndex !== dataBlockIndex) {\n\t\t\t\t\tdataBlock = this.getFullDataBlock(i);\n\t\t\t\t\tdataBlockIndex = newDataBlockIndex;\n\t\t\t\t}\n\t\t\t\tyield this.getDataBlock(dataBlock, i % maxChunkSize);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate getFullDataBlock(index: number) {\n\t\tlet pointerIndex = Math.floor(index / this.cachedMaxChunkSize);\n\t\tlet cachedDataBlock = this.cachedFullDataBlock[pointerIndex];\n\t\tif(cachedDataBlock) {\n\t\t\treturn cachedDataBlock;\n\t\t}\n\t\tif(pointerIndex >= this.pointerStack.length) {\n\t\t\t// Only let a single thread append a new chunk at a time - otherwise two concurrent inserts landing in a new\n\t\t\t// chunk would each allocate + push a buffer, orphaning one and leaking memory\n\t\t\tlock(this.growLock);\n\t\t\ttry {\n\t\t\t\t// Re-check under the lock: another thread may have already appended the chunk while we were waiting\n\t\t\t\twhile(pointerIndex >= this.pointerStack.length) {\n\t\t\t\t\tlet newArray = this.memory.allocUI32(this.cachedMaxChunkSize * this.cachedDataLength * this.cachedByteMultipler);\n\t\t\t\t\tthis.pointerStack.push(newArray.pointer);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tunlock(this.growLock);\n\t\t\t}\n\t\t}\n\n\t\tlet array = new AllocatedMemory(this.memory, getPointer(this.pointerStack.at(pointerIndex)));\n\n\t\tlet blockLength = this.cachedDataLength * this.cachedMaxChunkSize;\n\t\tlet data: T;\n\t\tswitch(this.cachedType) {\n\t\t\tcase TYPE.int32:\n\t\t\t\tdata = new Int32Array(array.data.buffer, array.bufferByteOffset, blockLength) as T;\n\t\t\t\tbreak;\n\t\t\tcase TYPE.uint32:\n\t\t\t\tdata = new Uint32Array(array.data.buffer, array.bufferByteOffset, blockLength) as T;\n\t\t\t\tbreak;\n\t\t\tcase TYPE.float32:\n\t\t\t\tdata = new Float32Array(array.data.buffer, array.bufferByteOffset, blockLength) as T;\n\t\t\t\tbreak;\n\t\t\tcase TYPE.float64:\n\t\t\t\tdata = new Float64Array(array.data.buffer, array.bufferByteOffset, blockLength) as T;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unknown data block type ${this.cachedType}`);\n\t\t}\n\n\t\tthis.cachedFullDataBlock[pointerIndex] = data;\n\t\treturn data;\n\t}\n\n\tprivate getDataBlock(rawData: T, index: number): T {\n\t\tconst dataLength = this.cachedDataLength;\n\t\tconst start = index * dataLength;\n\t\treturn rawData.subarray(start, start + dataLength) as T;\n\t}\n\n\tfree() {\n\t\tthis.recycleStack.free();\n\n\t\tfor(let pointer of this.pointerStack) {\n\t\t\tlet memory = new AllocatedMemory(this.memory, getPointer(pointer));\n\t\t\tmemory.free();\n\t\t}\n\t\tthis.pointerStack.free();\n\t\tthis.firstBlock.free();\n\t}\n\n\tgetSharedMemory(): SharedPoolMemory {\n\t\treturn {\n\t\t\tfirstBlock: this.firstBlock.getSharedMemory(),\n\t\t};\n\t}\n}\n\ninterface SharedPoolConfig<T extends Uint32Array | Int32Array | Float32Array | Float64Array> {\n\tmaxChunkSize?: number\n\ttype?: TypedArrayConstructor<T>\n\tdataLength?: number\n}\ninterface SharedPoolMemory {\n\tfirstBlock: SharedAllocatedMemory\n}\n\nexport type { SharedPoolConfig, SharedPoolMemory };\n"],"mappings":"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"}
|