export default class Mutex {
    constructor() {
        this.current = Promise.resolve();
    }

    /** @returns {Promise} */
    lock() {
        let resolveFun;
        const subPromise = new Promise(resolve => resolveFun = () => resolve());
        // Caller gets a promise that resolves when the current outstanding lock resolves
        const newPromise = this.current.then(() => resolveFun);
        // Don't allow the next request until the new promise is done
        this.current = subPromise;
        // Return the new promise
        return newPromise;
    };

    async runExclusively(cb) {
        const unlock = await this.lock();

        try {
            await cb();
        }
        finally {
            unlock();
        }
    }
}
