UNPKG

langium

Version:

A language engineering tool for the Language Server Protocol

75 lines 2.81 kB
/****************************************************************************** * Copyright 2023 TypeFox GmbH * This program and the accompanying materials are made available under the * terms of the MIT License, which is available in the project root. ******************************************************************************/ import { CancellationToken, CancellationTokenSource } from '../utils/cancellation.js'; import { Deferred, isOperationCancelled, startCancelableOperation } from '../utils/promise-utils.js'; export class DefaultWorkspaceLock { constructor() { this.previousTokenSource = new CancellationTokenSource(); this.writeQueue = []; this.readQueue = []; this.done = true; } write(action) { this.cancelWrite(); const tokenSource = startCancelableOperation(); this.previousTokenSource = tokenSource; return this.enqueue(this.writeQueue, action, tokenSource.token); } read(action) { return this.enqueue(this.readQueue, action); } enqueue(queue, action, cancellationToken = CancellationToken.None) { const deferred = new Deferred(); const entry = { action, deferred, cancellationToken }; queue.push(entry); this.performNextOperation(); return deferred.promise; } async performNextOperation() { if (!this.done) { return; } const entries = []; if (this.writeQueue.length > 0) { // Just perform the next write action entries.push(this.writeQueue.shift()); } else if (this.readQueue.length > 0) { // Empty the read queue and perform all actions in parallel entries.push(...this.readQueue.splice(0, this.readQueue.length)); } else { return; } this.done = false; await Promise.all(entries.map(async ({ action, deferred, cancellationToken }) => { try { // Move the execution of the action to the next event loop tick via `Promise.resolve()` const result = await Promise.resolve().then(() => action(cancellationToken)); deferred.resolve(result); } catch (err) { if (isOperationCancelled(err)) { // If the operation was cancelled, we don't want to reject the promise deferred.resolve(undefined); } else { deferred.reject(err); } } })); this.done = true; this.performNextOperation(); } cancelWrite() { this.previousTokenSource.cancel(); } } //# sourceMappingURL=workspace-lock.js.map