@daneren2005/shared-memory-objects 0.0.9 → 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 -191
- 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 @@
|
|
|
1
|
+
(function(f,m){typeof exports=="object"&&typeof module<"u"?m(exports):typeof define=="function"&&define.amd?define(["exports"],m):(f=typeof globalThis<"u"?globalThis:f||self,m(f.SharedMemoryObjects={}))})(this,function(f){"use strict";var me=Object.defineProperty;var Be=(f,m,T)=>m in f?me(f,m,{enumerable:!0,configurable:!0,writable:!0,value:T}):f[m]=T;var h=(f,m,T)=>(Be(f,typeof m!="symbol"?m+"":m,T),T);const X=Math.pow(2,20),v=Math.pow(2,12);function c(s,t=0){return _(Atomics.load(s,t))}function w(s,t=0){return Atomics.load(s,t)}function b(s,t=0,e,i){Atomics.store(s,t,g(e,i))}function N(s,t=0,e){Atomics.store(s,t,e)}function Ft(s,t,e,i,r,o){let a=g(r,o);return Atomics.compareExchange(s,t,a,g(e,i))===a}function U(s,t,e,i){return Atomics.compareExchange(s,t,i,e)===i}function _(s){return{bufferPosition:s&4095,bufferByteOffset:s>>>12}}function g(s,t){return s+(t<<12)}class u{constructor(t,e){h(this,"memory");h(this,"bufferPosition");h(this,"buffer");h(this,"data");this.memory=t,"buffer"in e?(this.data=e.data,this.buffer=e.buffer,this.bufferPosition=this.memory.buffers.indexOf(e.buffer)):(this.bufferPosition=e.bufferPosition,this.buffer=t.buffers[e.bufferPosition],this.data=new Uint32Array(this.buffer.buf,e.bufferByteOffset))}get bufferByteOffset(){return this.data.byteOffset}get pointer(){return g(this.bufferPosition,this.bufferByteOffset)}getArray(t,e,i){return new t(this.data.buffer,this.data.byteOffset+e*t.BYTES_PER_ELEMENT,i)}getArrayMemory(t,e){return{bufferPosition:this.bufferPosition,bufferByteOffset:this.bufferByteOffset+t*this.data.BYTES_PER_ELEMENT}}free(){this.buffer.free(this.data.byteOffset)}getSharedMemory(){return{bufferPosition:this.bufferPosition,bufferByteOffset:this.bufferByteOffset}}}const W=0,C=1;function p(s,t=0){for(;Atomics.compareExchange(s,t,W,C)!==W;)"WorkerGlobalScope"in self&&Atomics.wait(s,t,C)}function A(s,t=0){Atomics.compareExchange(s,t,C,W)!==C&&console.warn("We are unlocking when it was not locked!"),Atomics.notify(s,t)}const Dt=1,Rt={5120:"i8",5121:"u8",5122:"i16",5123:"u16",5124:"i32",5125:"u32",5126:"f32"},Yt={f32:Float32Array,f64:Float64Array},$t={i8:Int8Array,i16:Int16Array,i32:Int32Array},Ht={u8:Uint8Array,u8c:Uint8ClampedArray,u16:Uint16Array,u32:Uint32Array},Kt={i64:BigInt64Array,u64:BigUint64Array},zt={...Yt,...$t,...Ht},Gt=s=>{const t=Rt[s];return t!==void 0?t:s};function xt(s,...t){const e=Kt[s];return new(e||zt[Gt(s)])(...t)}const ot=0,at=1,nt=2,ft=3,lt=4,O=5,ht=6,Z=1,j=2,ct=8*4,q=0,V=1,B=2*4;class F{constructor(t={}){h(this,"buf");h(this,"start");h(this,"u8");h(this,"u32");h(this,"state");h(this,"lock");if(this.buf=t.buf?t.buf:new ArrayBuffer(t.size||4096),this.start=t.start!=null?R(Math.max(t.start,0),4):0,this.u8=new Uint8Array(this.buf),this.u32=new Uint32Array(this.buf),this.state=new Uint32Array(this.buf,this.start,ct/4),this.lock=new Int32Array(this.buf,this.start+this.state.byteLength-4,1),!t.skipInitialization){const e=t.align||8;if(e<8)throw new Error(`invalid alignment: ${e}, must be a pow2 and >= 8`);const i=this.initialTop(e),r=t.end!=null?Math.min(t.end,this.buf.byteLength):this.buf.byteLength;if(i>=r)throw new Error(`insufficient address range (0x${this.start.toString(16)} - 0x${r.toString(16)})`);this.align=e,this.doCompact=t.compact!==!1,this.doSplit=t.split!==!1,this.minSplit=t.minSplit||16,this.end=r,this.top=i,this._free=0,this._used=0}}stats(){const t=i=>{let r=0,o=0;for(;i;)if(r++,o+=this.blockSize(i),i=this.blockNext(i),i>this.end){console.error(`Trying to get stats for block past end of buffer: ${i} > ${this.end}`);break}return{count:r,size:o}},e=t(this._free);return{free:e,used:t(this._used),top:this.top,available:this.end-this.top+e.size,total:this.buf.byteLength}}callocAs(t,e,i=0){const r=this.mallocAs(t,e);return r&&r.fill(i),r}mallocAs(t,e){const i=this.malloc(e*Xt[t]);return i?xt(t,this.buf,i,e):void 0}calloc(t,e=0){const i=this.malloc(t);return i&&this.u8.fill(e,i,i+t),i}malloc(t){if(t<=0)return 0;p(this.lock);const e=R(t+B,this.align),i=this.end;let r=this.top,o=this._free,a=0;for(;o;){const l=this.blockSize(o),n=o+l>=r;if(n||l>=e){let d=this.mallocTop(o,a,l,e,n);return A(this.lock),d}a=o,o=this.blockNext(o)}if(o=r,r=o+e,r<=i){this.initBlock(o,e,this._used),this._used=o,this.top=r;let l=P(o);return A(this.lock),l}return A(this.lock),0}mallocTop(t,e,i,r,o){if(o&&t+r>this.end)return 0;if(e?this.unlinkBlock(e,t):this._free=this.blockNext(t),this.setBlockNext(t,this._used),this._used=t,o)this.top=t+this.setBlockSize(t,r);else if(this.doSplit){const a=i-r;a>=this.minSplit&&this.splitBlock(t,r,a)}return P(t)}realloc(t,e){if(e<=0)return 0;const i=D(t);let r=0,o=this._used,a=0;for(;o;){if(o===i){[r,a]=this.reallocBlock(o,e);break}o=this.blockNext(o)}return r&&r!==i&&this.u8.copyWithin(P(r),P(i),a),P(r)}reallocBlock(t,e){const i=this.blockSize(t),r=t+i,o=r>=this.top,a=R(e+B,this.align);if(a<=i){if(this.doSplit){const l=i-a;l>=this.minSplit?this.splitBlock(t,a,l):o&&(this.top=t+a)}else o&&(this.top=t+a);return[t,r]}return o&&t+a<this.end?(this.top=t+this.setBlockSize(t,a),[t,r]):(this.free(t),[D(this.malloc(e)),r])}reallocArray(t,e){if(t.buffer!==this.buf)return;const i=this.realloc(t.byteOffset,e*t.BYTES_PER_ELEMENT);return i?new t.constructor(this.buf,i,e):void 0}bytesFor(t){let e;if(typeof t!="number"){if(t.buffer!==this.buf)return;e=t.byteOffset}else e=t;e=D(e);let i=this._used;for(;i;){if(i===e)return this.blockSize(e)-B;i=this.blockNext(i)}}lengthOf(t){let e=this.bytesFor(t);if(e)return e/this.u32.BYTES_PER_ELEMENT}free(t){let e;if(typeof t!="number"){if(t.buffer!==this.buf)return!1;e=t.byteOffset}else e=t;p(this.lock),e=D(e);let i=this._used,r=0;for(;i;){if(i===e)return r?this.unlinkBlock(r,i):this._used=this.blockNext(i),this.insert(i),this.doCompact&&this.compact(),A(this.lock),!0;r=i,i=this.blockNext(i)}return A(this.lock),!1}freeAll(){this._free=0,this._used=0,this.top=this.initialTop()}release(){return delete this.u8,delete this.u32,delete this.state,delete this.buf,!0}get align(){return this.state[lt]}set align(t){this.state[lt]=t}get end(){return this.state[ft]}set end(t){this.state[ft]=t}get top(){return Atomics.load(this.state,nt)}set top(t){Atomics.store(this.state,nt,t)}get _free(){return Atomics.load(this.state,ot)}set _free(t){Atomics.store(this.state,ot,t)}get _used(){return Atomics.load(this.state,at)}set _used(t){Atomics.store(this.state,at,t)}get doCompact(){return!!(this.state[O]&Z)}set doCompact(t){t?this.state[O]|=1<<Z-1:this.state[O]&=~Z}get doSplit(){return!!(this.state[O]&j)}set doSplit(t){t?this.state[O]|=1<<j-1:this.state[O]&=~j}get minSplit(){return this.state[ht]}set minSplit(t){if(t<=B)throw new Error(`illegal min split threshold: ${t}, require at least ${B+1}`);this.state[ht]=t}blockSize(t){return Atomics.load(this.u32,(t>>2)+q)}setBlockSize(t,e){return Atomics.store(this.u32,(t>>2)+q,e),e}blockNext(t){return Atomics.load(this.u32,(t>>2)+V)}setBlockNext(t,e){Atomics.store(this.u32,(t>>2)+V,e)}initBlock(t,e,i){const r=t>>>2;return Atomics.store(this.u32,r+q,e),Atomics.store(this.u32,r+V,i),t}unlinkBlock(t,e){this.setBlockNext(t,this.blockNext(e))}splitBlock(t,e,i){this.insert(this.initBlock(t+this.setBlockSize(t,e),i,0)),this.doCompact&&this.compact()}initialTop(t=this.align){return R(this.start+ct+B,t)-B}compact(){let t=this._free,e=0,i=0,r,o=!1;for(;t;){for(r=t,i=this.blockNext(t);i&&r+this.blockSize(r)===i;)r=i,i=this.blockNext(i);if(r!==t){const a=r-t+this.blockSize(r);this.setBlockSize(t,a);const l=this.blockNext(r);let n=this.blockNext(t);for(;n&&n!==l;){const d=this.blockNext(n);this.setBlockNext(n,0),n=d}this.setBlockNext(t,l),o=!0}t+this.blockSize(t)>=this.top&&(this.top=t,e?this.unlinkBlock(e,t):this._free=this.blockNext(t)),e=t,t=this.blockNext(t)}return o}insert(t){let e=this._free,i=0;for(;e&&!(t<=e);)i=e,e=this.blockNext(e);i?this.setBlockNext(i,t):this._free=t,this.setBlockNext(t,e)}}const P=s=>s>0?s+B:0,D=s=>s>0?s-B:0,R=(s,t)=>(t--,s+t&~t),Xt={u8:1,u8c:1,i8:1,u16:2,i16:2,u32:4,i32:4,i64:8,u64:8,f32:4,f64:8},vt=["B","kB","MB","GB","TB","PB","EB","ZB","YB"],Wt=["B","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"],Zt=["b","kbit","Mbit","Gbit","Tbit","Pbit","Ebit","Zbit","Ybit"],jt=["b","kibit","Mibit","Gibit","Tibit","Pibit","Eibit","Zibit","Yibit"],ut=(s,t,e)=>{let i=s;return typeof t=="string"||Array.isArray(t)?i=s.toLocaleString(t,e):(t===!0||e!==void 0)&&(i=s.toLocaleString(void 0,e)),i};function qt(s,t){if(!Number.isFinite(s))throw new TypeError(`Expected a finite number, got ${typeof s}: ${s}`);t={bits:!1,binary:!1,space:!0,...t};const e=t.bits?t.binary?jt:Zt:t.binary?Wt:vt,i=t.space?" ":"";if(t.signed&&s===0)return` 0${i}${e[0]}`;const r=s<0,o=r?"-":t.signed?"+":"";r&&(s=-s);let a;if(t.minimumFractionDigits!==void 0&&(a={minimumFractionDigits:t.minimumFractionDigits}),t.maximumFractionDigits!==void 0&&(a={maximumFractionDigits:t.maximumFractionDigits,...a}),s<1){const I=ut(s,t.locale,a);return o+I+i+e[0]}const l=Math.min(Math.floor(t.binary?Math.log(s)/Math.log(1024):Math.log10(s)/3),e.length-1);s/=(t.binary?1024:1e3)**l,a||(s=s.toPrecision(3));const n=ut(Number(s),t.locale,a),d=e[l];return o+n+i+d}const Vt=8192,dt=0,J=1,Y=2;class Jt{constructor(t){h(this,"buffers");h(this,"onGrowBufferHandlers",[]);h(this,"isClone");h(this,"memory");if(t&&"buffers"in t)this.buffers=t.buffers.map(e=>new F({buf:e,skipInitialization:!0})),this.memory=new u(this,{bufferPosition:0,bufferByteOffset:40}),this.isClone=!0;else{"SharedArrayBuffer"in globalThis||console.warn("SharedArrayBuffer is not working: falling back to ArrayBuffer");const e=(t==null?void 0:t.bufferSize)??Vt;if(e>X)throw new Error(`Buffer size ${e} is greater than max ${X} that we can reference with pointers`);let i=this.createBuffer(e);this.buffers=[i];const r=i.callocAs("u32",3);if(r)this.memory=new u(this,{bufferPosition:0,bufferByteOffset:r.byteOffset});else throw new Error("Failed to initialize first byte from buffer");this.memory.data[dt]=e,this.memory.data[J]=1,this.memory.data[Y]=(t==null?void 0:t.autoGrowSize)??100,this.isClone=!1;for(let o=1;o<((t==null?void 0:t.initialBuffers)??1);o++)this.buffers.push(this.createBuffer(e))}}get bufferSize(){return this.memory.data[dt]}addSharedBuffer(t){this.buffers[t.bufferPosition]=new F({buf:t.buffer,skipInitialization:!0})}growBuffer(){const t=this.createBuffer();let e=Atomics.add(this.memory.data,J,1);return this.buffers[e]=t,this.onGrowBufferHandlers.forEach(i=>i({bufferPosition:e,buffer:t.buf})),t}createBuffer(t){const e=t??this.bufferSize;let i;return"SharedArrayBuffer"in globalThis?i=new SharedArrayBuffer(e):i=new ArrayBuffer(e),new F({buf:i,compact:!1,split:!1})}addOnGrowBufferHandlers(t){this.onGrowBufferHandlers.push(t)}allocUI32(t){t=Math.ceil(t);for(let r=0;r<this.buffers.length;r++){const o=this.buffers[r];if(!o)continue;const a=o.callocAs("u32",t);if(a)return r===this.buffers.length-1&&Atomics.load(this.memory.data,J)===this.buffers.length&&this.memory.data[Y]<100&&this.memory.data[Y]>0&&o.top/o.end>this.memory.data[Y]/100&&this.growBuffer(),new u(this,{data:a,buffer:o})}if(this.buffers.length>=v)throw new Error(`Can't initialize a new buffer since it would have a position greater than the max of ${v}`);let e=this.growBuffer();const i=e.callocAs("u32",t);if(i)return new u(this,{data:i,buffer:e});throw new Error(`Unable to allocate ${t} numbers even after adding a new buffer`)}getSharedAlloc(t){if(this.buffers[t.bufferPosition]!==void 0)return new u(this,t)}get currentUsed(){return this.totalAllocated-this.buffers.reduce((t,e)=>t+e.stats().available,0)}get totalAllocated(){return this.buffers[0].buf.byteLength*this.buffers.length}prettyMemory(){return`${yt(this.currentUsed)} / ${yt(this.totalAllocated)}`}getSharedMemory(){return{buffers:this.buffers.map(t=>t.buf)}}}function yt(s){return qt(s,{binary:!0,minimumFractionDigits:1,maximumFractionDigits:1})}const mt=4,Bt=1,S=2;class y{constructor(t,e){h(this,"memory");h(this,"firstBlock");h(this,"uint16Array");h(this,"onDelete");if(this.memory=t,e&&"firstBlock"in e)this.firstBlock=new u(t,e.firstBlock),this.uint16Array=new Uint16Array(this.firstBlock.data.buffer,this.firstBlock.bufferByteOffset+(S+1)*Uint32Array.BYTES_PER_ELEMENT,2);else{e&&e.initWithBlock?this.firstBlock=new u(t,e.initWithBlock):this.firstBlock=t.allocUI32(mt),this.uint16Array=new Uint16Array(this.firstBlock.data.buffer,this.firstBlock.bufferByteOffset+(S+1)*Uint32Array.BYTES_PER_ELEMENT,2);const i=(e==null?void 0:e.type)??Uint32Array;i===Uint32Array?this.type=0:i===Int32Array?this.type=1:i===Float32Array&&(this.type=2),this.dataLength=(e==null?void 0:e.dataLength)??1}}get length(){return Atomics.load(this.firstBlock.data,S)}get type(){return Atomics.load(this.uint16Array,0)}set type(t){Atomics.store(this.uint16Array,0,t)}get dataLength(){return Math.max(1,Atomics.load(this.uint16Array,1))}set dataLength(t){Atomics.store(this.uint16Array,1,t)}insert(t){typeof t=="number"&&(t=[t]);let e=this.dataLength;if(t.length>e)throw new Error(`Can't insert ${t.length} array into shared list of ${e} dataLength`);let i=this.memory.allocUI32(Bt+e),r=this.getDataBlock(i.data),o=i.pointer;for(let n=0;n<t.length;n++)r instanceof Int32Array||r instanceof Uint32Array?Atomics.store(r,n,t[n]):r[n]=t[n];let a,l=!1;for(;!l;)a=w(this.firstBlock.data,1),l=U(this.firstBlock.data,1,o,a);if(a){let{bufferPosition:n,bufferByteOffset:d}=_(a),I=new Uint32Array(this.memory.buffers[n].buf,d,1);N(I,0,o)}else N(this.firstBlock.data,0,o);Atomics.add(this.firstBlock.data,S,1)}deleteMatch(t){for(let{data:e,index:i,deleteCurrent:r}of this)if(t(e,i))return r(),!0;return!1}deleteIndex(t){return t>=this.length||t<0?!1:this.deleteMatch((e,i)=>i===t)}deleteValue(t){return typeof t=="number"?this.deleteMatch(e=>e[0]===t):this.deleteMatch(e=>{if(e.length!==t.length)return!1;for(let i=0;i<e.length;i++)if(e[i]!==t[i])return!1;return!0})}clear(){let t,e,i=!1;for(;!i;){if(t=w(this.firstBlock.data,0),e=w(this.firstBlock.data,1),!e)return;i=U(this.firstBlock.data,1,0,e)}if(!t)return;U(this.firstBlock.data,0,0,t);let r=0,o=t;for(;o;){let{bufferPosition:a,bufferByteOffset:l}=_(o),n=this.memory.buffers[a];if(!n)break;let d=new Uint32Array(n.buf,l,2);o=w(d,0),r++,this.onDelete&&this.onDelete(this.getDataBlock(d)),n.free(d.byteOffset)}Atomics.sub(this.firstBlock.data,S,r)}*[Symbol.iterator](){let t=0,{bufferPosition:e,bufferByteOffset:i}=c(this.firstBlock.data,0),r=this.firstBlock.data,o=0,a=0;for(;i;){let l=this.memory.buffers[e];if(!l)return;let n=new Uint32Array(l.buf,i,2),d=this.getDataBlock(n),I=e,ye=i;({bufferPosition:e,bufferByteOffset:i}=c(n,0));let Ct=!0;yield{data:d,index:t,deleteCurrent:()=>{b(r,0,e,i),i||b(this.firstBlock.data,1,o,a),this.onDelete&&this.onDelete(this.getDataBlock(n)),l.free(n.byteOffset),Atomics.sub(this.firstBlock.data,S,1),Ct=!1}},Ct&&(r=n,o=I,a=ye,t++)}}forEach(t){for(let e of this)t(e.data)}getSharedMemory(){return{firstBlock:this.firstBlock.getSharedMemory()}}getDataBlock(t){const e=t.byteOffset+Bt*t.BYTES_PER_ELEMENT;switch(this.type){case 1:return new Int32Array(t.buffer,e,this.dataLength);case 0:return new Uint32Array(t.buffer,e,this.dataLength);case 2:return new Float32Array(t.buffer,e,this.dataLength);default:throw new Error(`Unknown data block type ${this.type}`)}}free(){let{bufferPosition:t,bufferByteOffset:e}=c(this.firstBlock.data,0);for(;e;){let i=new u(this.memory,{bufferPosition:t,bufferByteOffset:e});({bufferPosition:t,bufferByteOffset:e}=c(i.data,0)),this.onDelete&&this.onDelete(this.getDataBlock(i.data)),i.free()}this.firstBlock.free()}}h(y,"ALLOCATE_COUNT",mt);const bt=10,z=class z{constructor(t,e){h(this,"memory");h(this,"pointerMemory");h(this,"lock");if(this.memory=t,e)this.pointerMemory=new u(t,e.firstBlock);else{this.pointerMemory=t.allocUI32(z.ALLOCATE_COUNT);let i=t.allocUI32(bt);b(this.pointerMemory.data,0,i.bufferPosition,i.bufferByteOffset),Atomics.store(this.pointerMemory.data,3,bt)}this.lock=new Int32Array(this.pointerMemory.data.buffer,this.pointerMemory.bufferByteOffset+Uint32Array.BYTES_PER_ELEMENT,1)}get hashMemory(){return new u(this.memory,c(this.pointerMemory.data,0))}get length(){return Atomics.load(this.pointerMemory.data,2)}get maxHash(){return Atomics.load(this.pointerMemory.data,3)}set(t,e){this.length>=this.maxHash*2&&this.growHashTable();let i=$(t);this.setHashKey(this.hashMemory,this.maxHash,i,e)&&Atomics.add(this.pointerMemory.data,2,1)}setHashKey(t,e,i,r){let o=this.hash(i,e),a,l=c(t.data,o);if(l.bufferByteOffset===0){a=new y(this.memory,{dataLength:2});let d=a.getSharedMemory();b(t.data,o,d.firstBlock.bufferPosition,d.firstBlock.bufferByteOffset)}else a=new y(this.memory,{firstBlock:l});let n=!0;return a.deleteValue(i)&&(n=!1),a.insert([i,r]),n}get(t){let e=$(t),i=this.hash(e,this.maxHash),r=c(this.hashMemory.data,i);if(r.bufferByteOffset===0)return;let o=new y(this.memory,{firstBlock:r});for(let{data:a}of o)if(a[0]===e)return a[1]}has(t){let e=$(t),i=this.hash(e,this.maxHash),r=c(this.hashMemory.data,i);if(r.bufferByteOffset===0)return!1;let o=new y(this.memory,{firstBlock:r});for(let{data:a}of o)if(a[0]===e)return!0;return!1}delete(t){let e=$(t),i=this.hash(e,this.maxHash),r=c(this.hashMemory.data,i);if(r.bufferByteOffset===0)return!1;let o=new y(this.memory,{firstBlock:r});for(let{data:a,deleteCurrent:l}of o)if(a[0]===e)return l(),Atomics.sub(this.pointerMemory.data,2,1),!0;return!1}growHashTable(){let t=this.maxHash,e=t*2,i=this.memory.allocUI32(e),r=this.hashMemory;for(let o=0;o<t;o++){let a=c(r.data,o);if(a.bufferByteOffset===0)continue;let l=new y(this.memory,{firstBlock:a});for(let{data:n}of l)this.setHashKey(i,e,n[0],n[1])}b(this.pointerMemory.data,0,i.bufferPosition,i.bufferByteOffset),Atomics.store(this.pointerMemory.data,3,e)}hash(t,e){return t%e}free(){for(let t=0;t<this.maxHash;t++){let e=c(this.hashMemory.data,t);if(e.bufferByteOffset===0)continue;new y(this.memory,{firstBlock:e}).free()}this.hashMemory.free(),this.pointerMemory.free()}getSharedMemory(){return{firstBlock:this.pointerMemory.getSharedMemory()}}};h(z,"ALLOCATE_COUNT",4);let Q=z;function $(s){return typeof s=="number"?s:typeof s=="string"?Qt(s):s}function Qt(s){let t=s.length,e=17^t,i=0,r;for(;t>=4;)r=s.charCodeAt(i)&255|(s.charCodeAt(++i)&255)<<8|(s.charCodeAt(++i)&255)<<16|(s.charCodeAt(++i)&255)<<14,r=(r&65535)*1540483477+(((r>>>16)*1540483477&65535)<<16),r^=r>>>14,r=(r&65535)*1540483477+(((r>>>16)*1540483477&65535)<<16),e=(e&65535)*1540483477+(((e>>>16)*1540483477&65535)<<16)^r,t-=4,++i;switch(t){case 3:e^=(s.charCodeAt(i+2)&255)<<16;case 2:e^=(s.charCodeAt(i+1)&255)<<8;case 1:e^=s.charCodeAt(i)&255,e=(e&65535)*1540483477+(((e>>>16)*1540483477&65535)<<16)}return e^=e>>>13,e=(e&65535)*1540483477+(((e>>>16)*1540483477&65535)<<16),e^=e>>>15,e=e>>>0,e}class te{constructor(t,e){h(this,"memory");h(this,"list");this.memory=t,e?this.list=new y(t,e):this.list=new y(t)}get length(){return this.list.length}insert(t){this.list.insert(g(t.memory.bufferPosition,t.memory.bufferByteOffset))}delete(t){return this.list.deleteValue(g(t.memory.bufferPosition,t.memory.bufferByteOffset))}*[Symbol.iterator](){let t=this.list[Symbol.iterator]();for(let{data:e}of t){let{bufferPosition:i,bufferByteOffset:r}=c(e,0),o=new u(this.memory,{bufferPosition:i,bufferByteOffset:r});yield this.createItem(o)}}forEach(t){for(let e of this)t(e)}find(t){for(let e of this)if(t(e))return e}getSharedMemory(){return this.list.getSharedMemory()}free(){for(let t of this)"free"in t&&typeof t.free=="function"?t.free():t.memory.free();this.list.free()}}const At={1:Uint8Array,2:Uint16Array},H=0,kt=1,Et=2,gt=3,G=class G{constructor(t,e){h(this,"memory");h(this,"allocatedMemory");h(this,"lock");h(this,"cachedPointer");h(this,"cachedString");this.memory=t,typeof e=="string"?(this.allocatedMemory=this.memory.allocUI32(G.ALLOCATE_COUNT),this.lock=new Int32Array(this.allocatedMemory.data.buffer,this.allocatedMemory.bufferByteOffset+gt*this.allocatedMemory.data.BYTES_PER_ELEMENT),this.updateString(e)):(this.allocatedMemory=new u(t,e),this.lock=new Int32Array(this.allocatedMemory.data.buffer,this.allocatedMemory.bufferByteOffset+gt*this.allocatedMemory.data.BYTES_PER_ELEMENT),"value"in e&&this.updateString(e.value))}updateString(t){let e=this.createString(t);p(this.lock),N(this.allocatedMemory.data,H,e.pointer),Atomics.store(this.allocatedMemory.data,kt,t.length),Atomics.store(this.allocatedMemory.data,Et,e.charType),A(this.lock),this.cachedPointer=e.pointer,this.cachedString=t}createString(t){if(t==="")return{pointer:0,charType:1};let e=[];for(let n=0;n<t.length;n++)e.push(t.charCodeAt(n));let r=Math.max(...e)>255?2:1,o=At[r],a=this.memory.allocUI32(Math.ceil(t.length/(4/o.BYTES_PER_ELEMENT))),l=new o(a.data.buffer,a.data.byteOffset,t.length);for(let n=0;n<t.length;n++)l[n]=t.charCodeAt(n);return{pointer:a.pointer,charType:r}}get value(){let t=w(this.allocatedMemory.data,H);if(this.cachedPointer===t&&this.cachedString!==void 0)return this.cachedString;if(t===0)return"";let{bufferPosition:e,bufferByteOffset:i}=_(t);p(this.lock);let r=Atomics.load(this.allocatedMemory.data,Et),o=At[r],a=Atomics.load(this.allocatedMemory.data,kt),l=new o(this.memory.buffers[e].buf,i,a),n=String.fromCharCode.apply(null,l);return A(this.lock),this.cachedPointer=t,this.cachedString=n,n}set value(t){let{bufferPosition:e,bufferByteOffset:i}=c(this.allocatedMemory.data,H);this.updateString(t),i&&this.memory.buffers[e].free(i)}getSharedMemory(){return this.allocatedMemory.getSharedMemory()}get pointer(){return this.allocatedMemory.pointer}free(){let{bufferPosition:t,bufferByteOffset:e}=c(this.allocatedMemory.data,H);e&&this.memory.buffers[t].free(e),this.allocatedMemory.free()}};h(G,"ALLOCATE_COUNT",4);let tt=G;const k=1,Tt=2,wt=3,ee=4,x=class x{constructor(t,e){h(this,"memory");h(this,"firstBlock");h(this,"uint16Array");h(this,"cachedFullDataBlock");h(this,"cachedPointer");if(this.memory=t,e&&"firstBlock"in e)this.firstBlock=new u(t,e.firstBlock),this.uint16Array=new Uint16Array(this.firstBlock.data.buffer,this.firstBlock.bufferByteOffset+wt*Uint32Array.BYTES_PER_ELEMENT,2);else{this.firstBlock=t.allocUI32(x.ALLOCATE_COUNT),this.uint16Array=new Uint16Array(this.firstBlock.data.buffer,this.firstBlock.bufferByteOffset+wt*Uint32Array.BYTES_PER_ELEMENT,2);let i=(e==null?void 0:e.dataLength)??1,r=(e==null?void 0:e.bufferLength)??ee,o=t.allocUI32(r*i);b(this.firstBlock.data,0,o.bufferPosition,o.bufferByteOffset),this.bufferLength=r;const a=(e==null?void 0:e.type)??Uint32Array;a===Uint32Array?this.type=0:a===Int32Array?this.type=1:a===Float32Array&&(this.type=2),this.dataLength=i}this.cachedPointer=this.firstBlock.data[0],this.cachedFullDataBlock=this.getFullDataBlock(this.dataLength)}get length(){return Atomics.load(this.firstBlock.data,k)}get type(){return this.uint16Array[0]}set type(t){Atomics.store(this.uint16Array,0,t)}get dataLength(){return Math.max(1,this.uint16Array[1])}set dataLength(t){Atomics.store(this.uint16Array,1,t)}get bufferLength(){return Atomics.load(this.firstBlock.data,Tt)}set bufferLength(t){Atomics.store(this.firstBlock.data,Tt,t)}at(t){let e=this.length;if(t>=e||t<0)throw new Error(`${t} is out of bounds ${e}`);let i=c(this.firstBlock.data,0),r=new u(this.memory,i);return this.getDataBlock(r.data,t)}get(t,e=0){if(e>=this.dataLength)throw new Error(`${e} is out of dataLength bounds ${this.dataLength}`);return this.at(t)[e]}push(t){typeof t=="number"&&(t=[t]);let e=this.dataLength;if(t.length>e)throw new Error(`Can't insert ${t.length} array into shared list of ${e} dataLength`);let i=this.getFullDataBlock(e),r=this.length;return i.set(t,e*r),Atomics.add(this.firstBlock.data,k,k)+1>=this.bufferLength&&this.growBuffer(),r}pop(){let t=Atomics.sub(this.firstBlock.data,k,k),e=c(this.firstBlock.data,0),i=new u(this.memory,e);return this.getDataBlock(i.data,t-1)}deleteIndex(t){let e=this.length;if(t>=e||t<0)throw new Error(`${t} is out of bounds ${e}`);let i=this.dataLength,r=this.getFullDataBlock(i);for(let o=t;o<e;o++)for(let a=0;a<i;a++)r[o*i+a]=r[(o+1)*i+a];Atomics.sub(this.firstBlock.data,k,k)}clear(){this.firstBlock.data[k]=0}*[Symbol.iterator](){let t=c(this.firstBlock.data,0),e=new u(this.memory,t);for(let i=0;i<this.length;i++)yield this.getDataBlock(e.data,i)}getFullDataBlock(t){let e=Atomics.load(this.firstBlock.data,0);if(this.cachedPointer===e&&this.cachedFullDataBlock)return this.cachedFullDataBlock;let i=_(e),r=new u(this.memory,i),o;switch(this.type){case 1:o=new Int32Array(r.data.buffer,r.bufferByteOffset,t*this.bufferLength);break;case 0:o=new Uint32Array(r.data.buffer,r.bufferByteOffset,t*this.bufferLength);break;case 2:o=new Float32Array(r.data.buffer,r.bufferByteOffset,t*this.bufferLength);break;default:throw new Error(`Unknown data block type ${this.type}`)}return this.cachedPointer=e,this.cachedFullDataBlock=o,o}getDataBlock(t,e){switch(this.type){case 1:return new Int32Array(t.buffer,t.byteOffset+e*this.dataLength*4,this.dataLength);case 0:return new Uint32Array(t.buffer,t.byteOffset+e*this.dataLength*4,this.dataLength);case 2:return new Float32Array(t.buffer,t.byteOffset+e*this.dataLength*4,this.dataLength);default:throw new Error(`Unknown data block type ${this.type}`)}}growBuffer(){let e=this.bufferLength*2,i=this.dataLength,r=c(this.firstBlock.data,0),o=new u(this.memory,r),a=this.getFullDataBlock(i),l=this.memory.allocUI32(e*i),n;switch(this.type){case 1:n=new Int32Array(l.data.buffer,l.bufferByteOffset,i*this.bufferLength);break;case 0:n=new Uint32Array(l.data.buffer,l.bufferByteOffset,i*this.bufferLength);break;case 2:n=new Float32Array(l.data.buffer,l.bufferByteOffset,i*this.bufferLength);break;default:throw new Error(`Unknown data block type ${this.type}`)}n.set(a),b(this.firstBlock.data,0,l.bufferPosition,l.bufferByteOffset),this.bufferLength=e,o.free()}free(){let t=c(this.firstBlock.data,0);new u(this.memory,t).free(),this.firstBlock.free()}getSharedMemory(){return{firstBlock:this.firstBlock.getSharedMemory()}}};h(x,"ALLOCATE_COUNT",4);let et=x;class _t{constructor(t,e){h(this,"heap");h(this,"list");h(this,"cache",new Map);e?this.list=new y(t,e):this.list=new y(t),this.heap=t,this.list.onDelete=i=>{let r=Atomics.load(i,0);if(r){let o=this.cache.get(r);o||(o=this.initItem(r)),o&&(o.free(),this.cache.delete(r))}}}get length(){return this.list.length}clear(){this.list.clear(),this.cache.clear()}insert(t){this.list.insert(t.pointer),this.cache.set(t.pointer,t)}delete(t){return this.cache.delete(t.pointer),this.list.deleteValue(t.pointer)}getByPointer(t){let e=this.cache.get(t);return e||(e=this.initItem(t),e&&this.cache.set(t,e)),e}*[Symbol.iterator](){let t=this.list[Symbol.iterator]();for(let{data:e,deleteCurrent:i}of t){let r=Atomics.load(e,0);if(!r)continue;let o=this.cache.get(r);o||(o=this.initItem(r),o&&this.cache.set(r,o)),o&&(yield{item:o,deleteCurrent:i})}}forEach(t,e){for(let{item:i}of this)(!e||e(i))&&t(i)}find(t){for(let{item:e}of this)if(t(e))return e}filter(t){let e=[];for(let{item:i}of this)t(i)&&e.push(i);return e}map(t){const e=[];for(let{item:i}of this)e.push(t(i));return e}getSharedMemory(){return this.list.getSharedMemory()}free(){this.list.free(),this.cache.clear()}}h(_t,"ALLOCATE_COUNT",y.ALLOCATE_COUNT);const Ot=new ArrayBuffer(4),St=new Uint32Array(Ot),K=new Uint16Array(Ot);function ie(s,t){return Lt(Atomics.load(s,t))}function re(s,t,e,i){Atomics.store(s,t,Mt(e,i))}function Lt(s){return St[0]=s,[K[0],K[1]]}function Mt(s,t){return K[0]=s,K[1]=t,St[0]}const pt=new ArrayBuffer(8),Pt=new BigUint64Array(pt),E=new Uint16Array(pt);function se(s,t){return Pt[0]=Atomics.load(s,t),[E[0],E[1],E[2],E[3]]}function oe(s,t,e,i,r,o=0){E[0]=e,E[1]=i,E[2]=r,E[3]=o,Atomics.store(s,t,Pt[0])}const It=new ArrayBuffer(4),Nt=new Float32Array(It),Ut=new Int32Array(It);function ae(s,t){return it(Atomics.load(s,t))}function ne(s,t,e){Atomics.store(s,t,rt(e))}function it(s){return Ut[0]=s,Nt[0]}function rt(s){return Nt[0]=s,Ut[0]}function fe(s,t,e){return it(Atomics.exchange(s,t,rt(e)))}const L=0,st=1,M=2;function le(s,t=0){for(;Atomics.compareExchange(s,t,L,st)===M;)Atomics.wait(s,t,M);Atomics.add(s,t+1,1)}function he(s,t=0){let e=Atomics.compareExchange(s,t,L,M);for(;e!==L;)Atomics.wait(s,t,e),e=Atomics.compareExchange(s,t,L,M)}function ce(s,t=0){Atomics.sub(s,t+1,1)-1<=0&&(Atomics.compareExchange(s,t,st,L)!==st&&console.warn("We are unlocking when it was not read locked!"),Atomics.notify(s,t))}function ue(s,t=0){Atomics.compareExchange(s,t,M,L)!==M&&console.warn("We are unlocking when it was not write locked!"),Atomics.notify(s,t)}const de=2;f.AllocatedMemory=u,f.BYTE_OFFSET_BIT_COUNT=20,f.CachedItemList=_t,f.MAX_BYTE_OFFSET_LENGTH=X,f.MAX_POSITION_LENGTH=v,f.MemoryBuffer=F,f.MemoryHeap=Jt,f.POSITION_BIT_COUNT=12,f.READ_WRITE_LOCK_ALLOCATE_COUNT=de,f.SIMPLE_LOCK_ALLOCATE_COUNT=Dt,f.SharedList=y,f.SharedMap=Q,f.SharedPointerList=te,f.SharedString=tt,f.SharedVector=et,f.convert16To32=Mt,f.convert32To16=Lt,f.convertFloat32ToInt32=rt,f.convertInt32ToFloat32=it,f.createPointer=g,f.exchangeFloat32=fe,f.getPointer=_,f.load16From32=ie,f.load16From64=se,f.loadFloat32=ae,f.loadPointer=c,f.loadRawPointer=w,f.lock=p,f.readLock=le,f.readUnlock=ce,f.replacePointer=Ft,f.replaceRawPointer=U,f.store16In32=re,f.store16In64=oe,f.storeFloat32=ne,f.storePointer=b,f.storeRawPointer=N,f.unlock=A,f.writeLock=he,f.writeUnlock=ue,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { TypedArray } from './interfaces/typed-array';
|
|
2
|
+
import { TypedArrayConstructor } from './interfaces/typed-array-constructor';
|
|
3
|
+
import { default as MemoryBuffer } from './memory-buffer';
|
|
4
|
+
import { default as MemoryHeap } from './memory-heap';
|
|
5
|
+
export default class AllocatedMemory {
|
|
6
|
+
private readonly memory;
|
|
7
|
+
readonly bufferPosition: number;
|
|
8
|
+
get bufferByteOffset(): number;
|
|
9
|
+
get pointer(): number;
|
|
10
|
+
private buffer;
|
|
11
|
+
data: Uint32Array;
|
|
12
|
+
constructor(memory: MemoryHeap, config: AllocatedMemoryConfig | SharedAllocatedMemory);
|
|
13
|
+
getArray<T extends TypedArray>(type: TypedArrayConstructor<T>, offset: number, length: number): T;
|
|
14
|
+
getArrayMemory(offset: number, length: number): SharedAllocatedMemory;
|
|
15
|
+
free(): void;
|
|
16
|
+
getSharedMemory(): SharedAllocatedMemory;
|
|
17
|
+
}
|
|
18
|
+
interface AllocatedMemoryConfig {
|
|
19
|
+
data: Uint32Array;
|
|
20
|
+
buffer: MemoryBuffer;
|
|
21
|
+
}
|
|
22
|
+
interface SharedAllocatedMemory {
|
|
23
|
+
bufferPosition: number;
|
|
24
|
+
bufferByteOffset: number;
|
|
25
|
+
}
|
|
26
|
+
export type { SharedAllocatedMemory };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { SharedAllocatedMemory } from './allocated-memory';
|
|
2
|
+
import { default as MemoryHeap } from './memory-heap';
|
|
3
|
+
import { default as SharedList, SharedListMemory } from './shared-list';
|
|
4
|
+
export default abstract class CachedItemList<T extends Item> implements Iterable<{
|
|
5
|
+
item: T;
|
|
6
|
+
deleteCurrent: () => void;
|
|
7
|
+
}> {
|
|
8
|
+
static readonly ALLOCATE_COUNT = 4;
|
|
9
|
+
protected heap: MemoryHeap;
|
|
10
|
+
protected list: SharedList;
|
|
11
|
+
protected cache: Map<number, T>;
|
|
12
|
+
constructor(heap: MemoryHeap, config?: CachedListConfig | SharedListMemory);
|
|
13
|
+
get length(): number;
|
|
14
|
+
clear(): void;
|
|
15
|
+
insert(item: T): void;
|
|
16
|
+
delete(item: T): boolean;
|
|
17
|
+
getByPointer(pointer: number): T | undefined;
|
|
18
|
+
protected abstract initItem(pointer: number): T | undefined;
|
|
19
|
+
[Symbol.iterator](): Generator<{
|
|
20
|
+
item: T;
|
|
21
|
+
deleteCurrent: () => void;
|
|
22
|
+
}, void, unknown>;
|
|
23
|
+
forEach(callback: (item: T) => void, filter?: (item: T) => boolean): void;
|
|
24
|
+
find(callback: (item: T) => boolean): T | undefined;
|
|
25
|
+
filter(callback: (entity: T) => boolean): Array<T>;
|
|
26
|
+
map<X>(callback: (item: T) => X): Array<X>;
|
|
27
|
+
getSharedMemory(): SharedListMemory;
|
|
28
|
+
free(): void;
|
|
29
|
+
}
|
|
30
|
+
export interface CachedListConfig {
|
|
31
|
+
initWithBlock: SharedAllocatedMemory;
|
|
32
|
+
}
|
|
33
|
+
interface Item {
|
|
34
|
+
pointer: number;
|
|
35
|
+
free: () => void;
|
|
36
|
+
}
|
|
37
|
+
export {};
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
type Pow2 = 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x40 | 0x80 | 0x100 | 0x200 | 0x400 | 0x800 | 0x1000 | 0x2000 | 0x4000 | 0x8000 | 0x10000 | 0x20000 | 0x40000 | 0x80000 | 0x100000 | 0x200000 | 0x400000 | 0x800000 | 0x1000000 | 0x2000000 | 0x4000000 | 0x8000000 | 0x10000000 | 0x20000000 | 0x40000000 | 0x80000000;
|
|
2
|
-
|
|
3
|
-
export type { Pow2 };
|
|
1
|
+
type Pow2 = 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x40 | 0x80 | 0x100 | 0x200 | 0x400 | 0x800 | 0x1000 | 0x2000 | 0x4000 | 0x8000 | 0x10000 | 0x20000 | 0x40000 | 0x80000 | 0x100000 | 0x200000 | 0x400000 | 0x800000 | 0x1000000 | 0x2000000 | 0x4000000 | 0x8000000 | 0x10000000 | 0x20000000 | 0x40000000 | 0x80000000;
|
|
2
|
+
export type { Pow2 };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type TypedArray = Float32Array | Float64Array | Int8Array | Int16Array | Int32Array | Uint8Array | Uint8ClampedArray | Uint16Array | Uint32Array;
|
|
1
|
+
export type TypedArray = Float32Array | Float64Array | Int8Array | Int16Array | Int32Array | Uint8Array | Uint8ClampedArray | Uint16Array | Uint32Array;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function readLock(data: Int32Array, index?: number): void;
|
|
2
|
+
export declare function writeLock(data: Int32Array, index?: number): void;
|
|
3
|
+
export declare function readUnlock(data: Int32Array, index?: number): void;
|
|
4
|
+
export declare function writeUnlock(data: Int32Array, index?: number): void;
|
|
5
|
+
export declare const READ_WRITE_LOCK_ALLOCATE_COUNT = 2;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { default as AllocatedMemory, SharedAllocatedMemory } from './allocated-memory';
|
|
2
|
+
import { default as MemoryBuffer } from './memory-buffer';
|
|
3
|
+
import { default as MemoryHeap, MemoryHeapMemory, GrowBufferData } from './memory-heap';
|
|
4
|
+
import { default as SharedList, SharedListMemory } from './shared-list';
|
|
5
|
+
import { default as SharedMap, SharedMapMemory } from './shared-map';
|
|
6
|
+
import { default as SharedPointerList } from './shared-pointer-list';
|
|
7
|
+
import { default as SharedString } from './shared-string';
|
|
8
|
+
import { default as SharedVector, SharedVectorMemory } from './shared-vector';
|
|
9
|
+
import { default as CachedItemList, CachedListConfig } from './cached-item-list';
|
|
10
|
+
export * from './interfaces/typed-array';
|
|
11
|
+
export * from './interfaces/typed-array-constructor';
|
|
12
|
+
export * from './utils/16-from-32-array';
|
|
13
|
+
export * from './utils/16-from-64-array';
|
|
14
|
+
export * from './utils/float32-atomics';
|
|
15
|
+
export * from './utils/pointer';
|
|
16
|
+
export * from './lock/simple-lock';
|
|
17
|
+
export * from './lock/read-write-lock';
|
|
18
|
+
export { AllocatedMemory, type SharedAllocatedMemory, MemoryBuffer, MemoryHeap, type MemoryHeapMemory, type GrowBufferData, SharedList, type SharedListMemory, SharedMap, type SharedMapMemory, SharedPointerList, SharedString, SharedVector, type SharedVectorMemory, CachedItemList, type CachedListConfig };
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { Pow2 } from './interfaces/pow2';
|
|
2
|
+
import { TypedArray } from './interfaces/typed-array';
|
|
3
|
+
export default class MemoryBuffer {
|
|
4
|
+
buf: ArrayBufferLike;
|
|
5
|
+
protected readonly start: number;
|
|
6
|
+
protected u8: Uint8Array;
|
|
7
|
+
protected u32: Uint32Array;
|
|
8
|
+
protected state: Uint32Array;
|
|
9
|
+
protected lock: Int32Array;
|
|
10
|
+
constructor(opts?: Partial<MemoryBufferConfig>);
|
|
11
|
+
stats(): Readonly<MemoryBufferStats>;
|
|
12
|
+
callocAs<T extends Type>(type: T, num: number, fill?: number): import('./utils/typedarray').TypedArrayTypeMap[T] | undefined;
|
|
13
|
+
mallocAs<T extends Type>(type: T, num: number): import('./utils/typedarray').TypedArrayTypeMap[T] | undefined;
|
|
14
|
+
calloc(bytes: number, fill?: number): number;
|
|
15
|
+
malloc(bytes: number): number;
|
|
16
|
+
private mallocTop;
|
|
17
|
+
realloc(ptr: number, bytes: number): number;
|
|
18
|
+
private reallocBlock;
|
|
19
|
+
reallocArray<T extends TypedArray>(array: T, num: number): T | undefined;
|
|
20
|
+
bytesFor(ptrOrArray: number | TypedArray): number | undefined;
|
|
21
|
+
lengthOf(ptrOrArray: number | TypedArray): number | undefined;
|
|
22
|
+
free(ptrOrArray: number | TypedArray): boolean;
|
|
23
|
+
freeAll(): void;
|
|
24
|
+
release(): boolean;
|
|
25
|
+
protected get align(): Pow2;
|
|
26
|
+
protected set align(x: Pow2);
|
|
27
|
+
get end(): number;
|
|
28
|
+
protected set end(x: number);
|
|
29
|
+
get top(): number;
|
|
30
|
+
protected set top(x: number);
|
|
31
|
+
protected get _free(): number;
|
|
32
|
+
protected set _free(block: number);
|
|
33
|
+
protected get _used(): number;
|
|
34
|
+
protected set _used(block: number);
|
|
35
|
+
protected get doCompact(): boolean;
|
|
36
|
+
protected set doCompact(flag: boolean);
|
|
37
|
+
protected get doSplit(): boolean;
|
|
38
|
+
protected set doSplit(flag: boolean);
|
|
39
|
+
protected get minSplit(): number;
|
|
40
|
+
protected set minSplit(x: number);
|
|
41
|
+
protected blockSize(block: number): number;
|
|
42
|
+
/**
|
|
43
|
+
* Sets & returns given block size.
|
|
44
|
+
*
|
|
45
|
+
* @param block -
|
|
46
|
+
* @param size -
|
|
47
|
+
*/
|
|
48
|
+
protected setBlockSize(block: number, size: number): number;
|
|
49
|
+
protected blockNext(block: number): number;
|
|
50
|
+
/**
|
|
51
|
+
* Sets block next pointer to `next`. Use zero to indicate list end.
|
|
52
|
+
*
|
|
53
|
+
* @param block -
|
|
54
|
+
*/
|
|
55
|
+
protected setBlockNext(block: number, next: number): void;
|
|
56
|
+
/**
|
|
57
|
+
* Initializes block header with given `size` and `next` pointer. Returns `block`.
|
|
58
|
+
*
|
|
59
|
+
* @param block -
|
|
60
|
+
* @param size -
|
|
61
|
+
* @param next -
|
|
62
|
+
*/
|
|
63
|
+
protected initBlock(block: number, size: number, next: number): number;
|
|
64
|
+
protected unlinkBlock(prev: number, block: number): void;
|
|
65
|
+
protected splitBlock(block: number, blockSize: number, excess: number): void;
|
|
66
|
+
protected initialTop(_align?: Pow2): number;
|
|
67
|
+
/**
|
|
68
|
+
* Traverses free list and attempts to recursively merge blocks
|
|
69
|
+
* occupying consecutive memory regions. Returns true if any blocks
|
|
70
|
+
* have been merged. Only called if `compact` option is enabled.
|
|
71
|
+
*/
|
|
72
|
+
protected compact(): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Inserts given block into list of free blocks, sorted by address.
|
|
75
|
+
*
|
|
76
|
+
* @param block -
|
|
77
|
+
*/
|
|
78
|
+
protected insert(block: number): void;
|
|
79
|
+
}
|
|
80
|
+
type Type = 'u8' | 'u8c' | 'i8' | 'u16' | 'i16' | 'u32' | 'i32' | 'f32' | 'f64';
|
|
81
|
+
interface MemoryBufferConfig {
|
|
82
|
+
/**
|
|
83
|
+
* Backing ArrayBuffer (or SharedArrayBuffer). If not given, a new
|
|
84
|
+
* one will be created with given `size`.
|
|
85
|
+
*/
|
|
86
|
+
buf: ArrayBufferLike;
|
|
87
|
+
/**
|
|
88
|
+
* Byte size for newly created ArrayBuffers (if `buf` is not given).
|
|
89
|
+
*
|
|
90
|
+
* @defaultValue 0x1000 (4KB)
|
|
91
|
+
*/
|
|
92
|
+
size: number;
|
|
93
|
+
/**
|
|
94
|
+
* Anchor index (byte address) inside the array buffer. The MemPool
|
|
95
|
+
* stores its internal state from the given address and heap space
|
|
96
|
+
* starts at least 32 bytes later (depending on chosen `align`
|
|
97
|
+
* value). Unlike allocator state variables, `start`` cannot be
|
|
98
|
+
* saved inside the array buffer itself. If the ArrayBuffer is
|
|
99
|
+
* passed to other consumers they must use the same start value.
|
|
100
|
+
* MUST be multiple of 4.
|
|
101
|
+
*
|
|
102
|
+
* @defaultValue 0
|
|
103
|
+
*/
|
|
104
|
+
start: number;
|
|
105
|
+
/**
|
|
106
|
+
* Byte address (+1) of the end of the memory region managed by the
|
|
107
|
+
* {@link MemPool}.
|
|
108
|
+
*
|
|
109
|
+
* @defaultValue end of the backing ArrayBuffer
|
|
110
|
+
*/
|
|
111
|
+
end: number;
|
|
112
|
+
/**
|
|
113
|
+
* Number of bytes to align memory blocks to. MUST be a power of 2
|
|
114
|
+
* and >= 8. Use 16 if the pool is being used for allocating memory
|
|
115
|
+
* used in SIMD operations.
|
|
116
|
+
*
|
|
117
|
+
* @defaultValue 8
|
|
118
|
+
*/
|
|
119
|
+
align: Pow2;
|
|
120
|
+
/**
|
|
121
|
+
* Flag to configure memory block compaction. If true,
|
|
122
|
+
* adjoining free blocks (in terms of address space) will be merged
|
|
123
|
+
* to minimize fragementation.
|
|
124
|
+
*
|
|
125
|
+
* @defaultValue true
|
|
126
|
+
*/
|
|
127
|
+
compact: boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Flag to configure memory block splitting. If true, and when the
|
|
130
|
+
* allocator is re-using a previously freed block larger than the
|
|
131
|
+
* requested size, the block will be split to minimize wasted/unused
|
|
132
|
+
* memory. The splitting behavior can further customized via the
|
|
133
|
+
* `minSplit` option.
|
|
134
|
+
*
|
|
135
|
+
* @defaultValue true
|
|
136
|
+
*/
|
|
137
|
+
split: boolean;
|
|
138
|
+
/**
|
|
139
|
+
* Only used if `split` behavior is enabled. Defines min number of
|
|
140
|
+
* excess bytes available in a block for memory block splitting to
|
|
141
|
+
* occur.
|
|
142
|
+
*
|
|
143
|
+
* @defaultValue 16, MUST be > 8
|
|
144
|
+
*/
|
|
145
|
+
minSplit: number;
|
|
146
|
+
/**
|
|
147
|
+
* Only needed when sharing the underlying ArrayBuffer. If true, the
|
|
148
|
+
* {@link MemPool} constructor will NOT initialize its internal state and
|
|
149
|
+
* assume the underlying ArrayBuffer has already been initialized by
|
|
150
|
+
* another {@link MemPool} instance. If this option is used, `buf` MUST be
|
|
151
|
+
* given.
|
|
152
|
+
*
|
|
153
|
+
* @defaultValue false
|
|
154
|
+
*/
|
|
155
|
+
skipInitialization: boolean;
|
|
156
|
+
}
|
|
157
|
+
interface MemoryBufferStats {
|
|
158
|
+
/**
|
|
159
|
+
* Free block stats.
|
|
160
|
+
*/
|
|
161
|
+
free: {
|
|
162
|
+
count: number;
|
|
163
|
+
size: number;
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* Used block stats.
|
|
167
|
+
*/
|
|
168
|
+
used: {
|
|
169
|
+
count: number;
|
|
170
|
+
size: number;
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* Current top address.
|
|
174
|
+
*/
|
|
175
|
+
top: number;
|
|
176
|
+
/**
|
|
177
|
+
* Bytes available
|
|
178
|
+
*/
|
|
179
|
+
available: number;
|
|
180
|
+
/**
|
|
181
|
+
* Total pool size.
|
|
182
|
+
*/
|
|
183
|
+
total: number;
|
|
184
|
+
}
|
|
185
|
+
export {};
|
|
@@ -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,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,40 @@
|
|
|
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
|
+
private cachedFullDataBlock?;
|
|
17
|
+
private cachedPointer;
|
|
18
|
+
constructor(memory: MemoryHeap, config?: SharedVectorConfig<T> | SharedVectorMemory);
|
|
19
|
+
at(index: number): T;
|
|
20
|
+
get(index: number, dataIndex?: number): number;
|
|
21
|
+
push(values: number | Array<number>): number;
|
|
22
|
+
pop(): T;
|
|
23
|
+
deleteIndex(index: number): void;
|
|
24
|
+
clear(): void;
|
|
25
|
+
[Symbol.iterator](): Generator<T, void, unknown>;
|
|
26
|
+
private getFullDataBlock;
|
|
27
|
+
private getDataBlock;
|
|
28
|
+
private growBuffer;
|
|
29
|
+
free(): void;
|
|
30
|
+
getSharedMemory(): SharedVectorMemory;
|
|
31
|
+
}
|
|
32
|
+
interface SharedVectorConfig<T extends Uint32Array | Int32Array | Float32Array> {
|
|
33
|
+
type?: TypedArrayConstructor<T>;
|
|
34
|
+
dataLength?: number;
|
|
35
|
+
bufferLength?: number;
|
|
36
|
+
}
|
|
37
|
+
interface SharedVectorMemory {
|
|
38
|
+
firstBlock: SharedAllocatedMemory;
|
|
39
|
+
}
|
|
40
|
+
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 };
|