@dhlx/rwlock-shared
Version:
A simple implementation of a read-write lock with shared read
2 lines (1 loc) • 2.51 kB
JavaScript
(function(i,s){typeof exports=="object"&&typeof module<"u"?s(exports):typeof define=="function"&&define.amd?define(["exports"],s):(i=typeof globalThis<"u"?globalThis:i||self,s(i.index={}))})(this,function(i){"use strict";var w=Object.defineProperty;var A=(i,s,n)=>s in i?w(i,s,{enumerable:!0,configurable:!0,writable:!0,value:n}):i[s]=n;var o=(i,s,n)=>A(i,typeof s!="symbol"?s+"":s,n);const s=d=>new Promise(t=>setTimeout(t,d)),e=class e{constructor(t,a={}){o(this,"state");o(this,"timeout",500);this.state=new Int32Array(t),this.timeout=a.timeout||this.timeout}async readLock(){for(;;){const t=Atomics.load(this.state,e.WRITER),a=Atomics.load(this.state,e.WAITERS);if(t===0&&a===0){Atomics.add(this.state,e.READERS,1);return}await Atomics.waitAsync(this.state,e.WRITER,0,this.timeout).value,await s(0)}}readUnlock(){Atomics.sub(this.state,e.READERS,1),Atomics.load(this.state,e.WAITERS)>0&&Atomics.notify(this.state,e.READERS)}async writeLock(){for(Atomics.add(this.state,e.WAITERS,1);;){const t=Atomics.load(this.state,e.READERS);if(t===0&&Atomics.compareExchange(this.state,e.WRITER,0,1)===0)break;t>0?await Atomics.waitAsync(this.state,e.READERS,0,this.timeout).value:await Atomics.waitAsync(this.state,e.WRITER,0,this.timeout).value,await s(0)}Atomics.sub(this.state,e.WAITERS,1)}writeUnlock(){Atomics.store(this.state,e.WRITER,0),Atomics.load(this.state,e.WAITERS)>0?Atomics.notify(this.state,e.WRITER,1):Atomics.notify(this.state,e.WRITER,Number.POSITIVE_INFINITY)}};o(e,"READERS",0),o(e,"WRITER",1),o(e,"WAITERS",2);let n=e;class h{constructor(t,a){o(this,"lock");o(this,"dataBuffer");o(this,"dataView");this.lock=new n(a),this.dataBuffer=t,this.dataView=new DataView(t)}async readData(){await this.lock.readLock();const t=this.deserialize();return this.lock.readUnlock(),t}async writeData(t){try{await this.lock.writeLock();const a=this.deserialize(),r=t(a);this.serialize(r)}finally{this.lock.writeUnlock()}}serialize(t){const a=JSON.stringify(t),c=new TextEncoder().encode(a);this.dataView.setUint32(0,c.length),c.forEach((u,f)=>this.dataView.setUint8(4+f,u))}deserialize(){const t=this.dataView.getUint32(0),a=new Uint8Array(this.dataBuffer.slice(4,t+4)),r=new Uint8Array(a),c=new TextDecoder;return c.decode(r)?JSON.parse(c.decode(r)??"{}"):{}}}function l(d=Int32Array.BYTES_PER_ELEMENT*3,t=1024){return{lockBuffer:new SharedArrayBuffer(d),dataBuffer:new SharedArrayBuffer(t)}}i.ReadWriteLock=n,i.SharedData=h,i.createSharedBuffers=l,Object.defineProperty(i,Symbol.toStringTag,{value:"Module"})});