import { Awaitable } from "@miniflare/shared" ; export class ReadWriteMutex { private readLockCount = 0 ; private writeLocked = false ; private readResolveQueue : ( ( ) => void ) [ ] = [ ] ; private writeResolveQueue : ( ( ) => void ) [ ] = [ ] ; private readLock ( ) { if ( this . writeResolveQueue . length === 0 && ! this . writeLocked ) { this . readLockCount ++ ; return ; } return new Promise ( ( resolve ) => this . readResolveQueue . push ( resolve ) ) ; } private writeLock ( ) { if ( this . readLockCount === 0 && ! this . writeLocked ) { this . writeLocked = true ; return ; } return new Promise ( ( resolve ) => this . writeResolveQueue . push ( resolve ) ) ; } private unlock ( ) { if ( this . readLockCount > 0 ) return ; if ( this . writeResolveQueue . length > 0 ) { this . writeLocked = true ; return this . writeResolveQueue . shift ( ) ?. ( ) ; } this . writeLocked = false ; this . readLockCount += this . readResolveQueue . length ; for ( const resolve of this . readResolveQueue ) resolve ( ) ; this . readResolveQueue . splice ( 0 , this . readResolveQueue . length ) ; } async runWithRead < T > ( closure ) { const acquireAwaitable = this . readLock ( ) ; if ( acquireAwaitable instanceof Promise ) await acquireAwaitable ; try { const awaitable = closure ( ) ; if ( awaitable instanceof Promise ) return await awaitable ; return awaitable ; } finally { this . readLockCount -- ; this . unlock ( ) ; } } async runWithWrite < T > ( closure ) { const acquireAwaitable = this . writeLock ( ) ; if ( acquireAwaitable instanceof Promise ) await acquireAwaitable ; try { const awaitable = closure ( ) ; if ( awaitable instanceof Promise ) return await awaitable ; return awaitable ; } finally { this . unlock ( ) ; } } }