igir
Version:
🕹 A zero-setup ROM collection manager that sorts, filters, extracts or archives, patches, and reports on collections of any size on any OS.
44 lines • 1.62 kB
JavaScript
import { Mutex } from 'async-mutex';
/**
* Wrapper for `async-mutex` {@link Mutex}es to run code exclusively for a key.
*/
export default class KeyedMutex {
constructor(maxSize) {
this.keyMutexes = new Map();
this.keyMutexesMutex = new Mutex();
this.keyMutexesLru = new Set();
this.maxSize = maxSize;
}
/**
* Run a {@link runnable} exclusively across all keys.
*/
async runExclusiveGlobally(runnable) {
return this.keyMutexesMutex.runExclusive(runnable);
}
/**
* Run a {@link runnable} exclusively for the given {@link key}.
*/
async runExclusiveForKey(key, runnable) {
const keyMutex = await this.runExclusiveGlobally(() => {
let mutex = this.keyMutexes.get(key);
if (mutex === undefined) {
mutex = new Mutex();
this.keyMutexes.set(key, mutex);
// Expire least recently used keys
[...this.keyMutexesLru]
.filter((lruKey) => !this.keyMutexes.get(lruKey)?.isLocked())
.slice(this.maxSize ?? Number.MAX_SAFE_INTEGER)
.forEach((lruKey) => {
this.keyMutexes.delete(lruKey);
this.keyMutexesLru.delete(lruKey);
});
}
// Mark this key as recently used
this.keyMutexesLru.delete(key);
this.keyMutexesLru = new Set([key, ...this.keyMutexesLru]);
return mutex;
});
return keyMutex.runExclusive(runnable);
}
}
//# sourceMappingURL=keyedMutex.js.map