Skip to content

Commit

Permalink
Fixes #209324
Browse files Browse the repository at this point in the history
  • Loading branch information
hediet committed Apr 2, 2024
1 parent b3d006c commit 54fea9e
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 58 deletions.
69 changes: 69 additions & 0 deletions src/vs/base/common/controlFlow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { BugIndicatingError } from 'vs/base/common/errors';

/*
* This file contains helper classes to manage control flow.
*/

/**
* Prevents code from being re-entrant.
*/
export class ReentrancyBarrier {
private _isOccupied = false;

/**
* Calls `runner` if the barrier is not occupied.
* During the call, the barrier becomes occupied.
*/
public runExclusivelyOrSkip(runner: () => void): void {
if (this._isOccupied) {
return;
}
this._isOccupied = true;
try {
runner();
} finally {
this._isOccupied = false;
}
}

/**
* Calls `runner`. If the barrier is occupied, throws an error.
* During the call, the barrier becomes active.
*/
public runExclusivelyOrThrow(runner: () => void): void {
if (this._isOccupied) {
throw new BugIndicatingError(`ReentrancyBarrier: reentrant call detected!`);
}
this._isOccupied = true;
try {
runner();
} finally {
this._isOccupied = false;
}
}

/**
* Indicates if some runner occupies this barrier.
*/
public get isOccupied() {
return this._isOccupied;
}

public makeExclusiveOrSkip<TFunction extends Function>(fn: TFunction): TFunction {
return ((...args: any[]) => {
if (this._isOccupied) {
return;
}
this._isOccupied = true;
try {
return fn(...args);
} finally {
this._isOccupied = false;
}
}) as any;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ITextModel } from 'vs/editor/common/model';
import { DetailedLineRangeMapping } from 'vs/workbench/contrib/mergeEditor/browser/model/mapping';
import { LineRangeEdit } from 'vs/workbench/contrib/mergeEditor/browser/model/editing';
import { LineRange } from 'vs/workbench/contrib/mergeEditor/browser/model/lineRange';
import { ReentrancyBarrier } from 'vs/workbench/contrib/mergeEditor/browser/utils';
import { ReentrancyBarrier } from '../../../../../base/common/controlFlow';
import { IMergeDiffComputer } from './diffComputer';
import { autorun, IObservable, IReader, ITransaction, observableSignal, observableValue, transaction } from 'vs/base/common/observable';
import { UndoRedoGroup } from 'vs/platform/undoRedo/common/undoRedo';
Expand All @@ -24,7 +24,7 @@ export class TextModelDiffs extends Disposable {
private _isDisposed = false;

public get isApplyingChange() {
return this._barrier.isActive;
return this._barrier.isOccupied;
}

constructor(
Expand All @@ -44,14 +44,14 @@ export class TextModelDiffs extends Disposable {

this._register(
baseTextModel.onDidChangeContent(
this._barrier.makeExclusive(() => {
this._barrier.makeExclusiveOrSkip(() => {
recomputeSignal.trigger(undefined);
})
)
);
this._register(
textModel.onDidChangeContent(
this._barrier.makeExclusive(() => {
this._barrier.makeExclusiveOrSkip(() => {
recomputeSignal.trigger(undefined);
})
)
Expand Down
48 changes: 1 addition & 47 deletions src/vs/workbench/contrib/mergeEditor/browser/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,60 +4,14 @@
*--------------------------------------------------------------------------------------------*/

import { ArrayQueue, CompareResult } from 'vs/base/common/arrays';
import { BugIndicatingError, onUnexpectedError } from 'vs/base/common/errors';
import { onUnexpectedError } from 'vs/base/common/errors';
import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { IObservable, autorunOpts, observableFromEvent } from 'vs/base/common/observable';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditor/codeEditorWidget';
import { IModelDeltaDecoration } from 'vs/editor/common/model';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';

export class ReentrancyBarrier {
private _isActive = false;

public get isActive() {
return this._isActive;
}

public makeExclusive<TFunction extends Function>(fn: TFunction): TFunction {
return ((...args: any[]) => {
if (this._isActive) {
return;
}
this._isActive = true;
try {
return fn(...args);
} finally {
this._isActive = false;
}
}) as any;
}

public runExclusively(fn: () => void): void {
if (this._isActive) {
return;
}
this._isActive = true;
try {
fn();
} finally {
this._isActive = false;
}
}

public runExclusivelyOrThrow(fn: () => void): void {
if (this._isActive) {
throw new BugIndicatingError();
}
this._isActive = true;
try {
fn();
} finally {
this._isActive = false;
}
}
}

export function setStyle(
element: HTMLElement,
style: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { autorunWithStore, IObservable } from 'vs/base/common/observable';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditor/codeEditorWidget';
import { ScrollType } from 'vs/editor/common/editorCommon';
import { DocumentLineRangeMap } from 'vs/workbench/contrib/mergeEditor/browser/model/mapping';
import { ReentrancyBarrier } from 'vs/workbench/contrib/mergeEditor/browser/utils';
import { ReentrancyBarrier } from '../../../../../base/common/controlFlow';
import { BaseCodeEditorView } from 'vs/workbench/contrib/mergeEditor/browser/view/editors/baseCodeEditorView';
import { IMergeEditorLayout } from 'vs/workbench/contrib/mergeEditor/browser/view/mergeEditor';
import { MergeEditorViewModel } from 'vs/workbench/contrib/mergeEditor/browser/view/viewModel';
Expand Down Expand Up @@ -62,7 +62,7 @@ export class ScrollSynchronizer extends Disposable {

this._store.add(
this.input1View.editor.onDidScrollChange(
this.reentrancyBarrier.makeExclusive((c) => {
this.reentrancyBarrier.makeExclusiveOrSkip((c) => {
if (c.scrollTopChanged) {
handleInput1OnScroll();
}
Expand All @@ -77,7 +77,7 @@ export class ScrollSynchronizer extends Disposable {

this._store.add(
this.input2View.editor.onDidScrollChange(
this.reentrancyBarrier.makeExclusive((c) => {
this.reentrancyBarrier.makeExclusiveOrSkip((c) => {
if (!this.model) {
return;
}
Expand Down Expand Up @@ -112,7 +112,7 @@ export class ScrollSynchronizer extends Disposable {
);
this._store.add(
this.inputResultView.editor.onDidScrollChange(
this.reentrancyBarrier.makeExclusive((c) => {
this.reentrancyBarrier.makeExclusiveOrSkip((c) => {
if (c.scrollTopChanged) {
if (this.shouldAlignResult) {
this.input1View.editor.setScrollTop(c.scrollTop, ScrollType.Immediate);
Expand Down Expand Up @@ -146,7 +146,7 @@ export class ScrollSynchronizer extends Disposable {
const baseView = this.baseView.read(reader);
if (baseView) {
store.add(baseView.editor.onDidScrollChange(
this.reentrancyBarrier.makeExclusive((c) => {
this.reentrancyBarrier.makeExclusiveOrSkip((c) => {
if (c.scrollTopChanged) {
if (!this.model) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { SideBySideEditor } from 'vs/workbench/browser/parts/editor/sideBySideEditor';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IEditorPane, IEditorPaneScrollPosition, isEditorPaneWithScrolling } from 'vs/workbench/common/editor';
import { ReentrancyBarrier } from 'vs/workbench/contrib/mergeEditor/browser/utils';
import { ReentrancyBarrier } from 'vs/base/common/controlFlow';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment } from 'vs/workbench/services/statusbar/browser/statusbar';

Expand Down Expand Up @@ -75,7 +75,7 @@ export class SyncScroll extends Disposable implements IWorkbenchContribution {

this.paneInitialScrollTop.set(pane, pane.getScrollPosition());
this.paneDisposables.add(pane.onDidChangeScroll(() =>
this._reentrancyBarrier.runExclusively(() => {
this._reentrancyBarrier.runExclusivelyOrSkip(() => {
this.onDidEditorPaneScroll(pane);
})
));
Expand Down

0 comments on commit 54fea9e

Please sign in to comment.