Skip to content

Commit

Permalink
add a new lifecycle event Restoring which is set when the editors/v…
Browse files Browse the repository at this point in the history
…iewlets are being restored (start). also in the lifecycle service replace `onDidChangePhase` with `when`
  • Loading branch information
jrieken committed Nov 7, 2017
1 parent b94569f commit ab17bb7
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 35 deletions.
14 changes: 8 additions & 6 deletions src/vs/platform/lifecycle/common/lifecycle.ts
Expand Up @@ -47,8 +47,9 @@ export enum StartupKind {

export enum LifecyclePhase {
Starting = 1,
Running = 2,
ShuttingDown = 3
Restoring = 2,
Running = 3,
ShuttingDown = 4
}

/**
Expand All @@ -70,9 +71,10 @@ export interface ILifecycleService {
readonly phase: LifecyclePhase;

/**
* An event that fire when the lifecycle phase has changed
* Returns a promise that resolves when a certain lifecycle phase
* has started.
*/
readonly onDidChangePhase: Event<LifecyclePhase>;
when(phase: LifecyclePhase): Thenable<void>;

/**
* Fired before shutdown happens. Allows listeners to veto against the
Expand All @@ -92,8 +94,8 @@ export interface ILifecycleService {
export const NullLifecycleService: ILifecycleService = {
_serviceBrand: null,
phase: LifecyclePhase.Running,
when() { return Promise.resolve(); },
startupKind: StartupKind.NewWindow,
onDidChangePhase: Event.None,
onWillShutdown: Event.None,
onShutdown: Event.None
};
Expand Down Expand Up @@ -127,4 +129,4 @@ export function handleVetos(vetos: (boolean | TPromise<boolean>)[], onError: (er
}

return TPromise.join(promises).then(() => lazyValue);
}
}
8 changes: 2 additions & 6 deletions src/vs/workbench/common/editor/textEditorModel.ts
Expand Up @@ -70,11 +70,7 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd
protected createTextEditorModel(value: string | IRawTextSource, resource?: URI, modeId?: string): TPromise<EditorModel> {
const firstLineText = this.getFirstLineText(value);
const mode = this.getOrCreateMode(this.modeService, modeId, firstLineText);

// To avoid flickering, give the mode at most 50ms to load. If the mode doesn't load in 50ms, proceed creating the model with a mode promise
return TPromise.any<any>([TPromise.timeout(50), mode]).then(() => {
return this.doCreateTextEditorModel(value, mode, resource);
});
return TPromise.as(this.doCreateTextEditorModel(value, mode, resource));
}

private doCreateTextEditorModel(value: string | IRawTextSource, mode: TPromise<IMode>, resource: URI): EditorModel {
Expand Down Expand Up @@ -166,4 +162,4 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd

super.dispose();
}
}
}
2 changes: 1 addition & 1 deletion src/vs/workbench/electron-browser/shell.ts
Expand Up @@ -165,7 +165,7 @@ export class WorkbenchShell {
const [instantiationService, serviceCollection] = this.initServiceCollection(parent.getHTMLElement());

// Workbench
this.workbench = instantiationService.createInstance(Workbench, parent.getHTMLElement(), workbenchContainer.getHTMLElement(), this.configuration, serviceCollection);
this.workbench = instantiationService.createInstance(Workbench, parent.getHTMLElement(), workbenchContainer.getHTMLElement(), this.configuration, serviceCollection, this.lifecycleService);
this.workbench.startup({
onWorkbenchStarted: (info: IWorkbenchStartedInfo) => {

Expand Down
6 changes: 4 additions & 2 deletions src/vs/workbench/electron-browser/workbench.ts
Expand Up @@ -79,7 +79,8 @@ import { ProgressService2 } from 'vs/workbench/services/progress/browser/progres
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { ILifecycleService, ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle';
import { ShutdownReason, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { LifecycleService } from 'vs/workbench/services/lifecycle/electron-browser/lifecycleService';
import { IWindowService, IWindowConfiguration as IWindowSettings, IWindowConfiguration, IPath } from 'vs/platform/windows/common/windows';
import { IMessageService } from 'vs/platform/message/common/message';
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
Expand Down Expand Up @@ -217,10 +218,10 @@ export class Workbench implements IPartService {
container: HTMLElement,
configuration: IWindowConfiguration,
serviceCollection: ServiceCollection,
private lifecycleService: LifecycleService,
@IInstantiationService private instantiationService: IInstantiationService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IStorageService private storageService: IStorageService,
@ILifecycleService private lifecycleService: ILifecycleService,
@IMessageService private messageService: IMessageService,
@IConfigurationService private configurationService: WorkspaceService,
@ITelemetryService private telemetryService: ITelemetryService,
Expand Down Expand Up @@ -339,6 +340,7 @@ export class Workbench implements IPartService {
const editorRestoreClock = time('restore:editors');
const restoredEditors: string[] = [];
compositeAndEditorPromises.push(this.resolveEditorsToOpen().then(inputs => {
this.lifecycleService.phase = LifecyclePhase.Restoring;
let editorOpenPromise: TPromise<IEditor[]>;
if (inputs.length) {
editorOpenPromise = this.editorService.openEditors(inputs.map(input => { return { input, position: EditorPosition.ONE }; }));
Expand Down
Expand Up @@ -17,7 +17,6 @@ import { ReportPerformanceIssueAction } from 'vs/workbench/electron-browser/acti
import { TPromise } from 'vs/base/common/winjs.base';
import { join } from 'path';
import { localize } from 'vs/nls';
import { toPromise, filterEvent } from 'vs/base/common/event';
import { readdir } from 'vs/base/node/pfs';
import { stopProfiling } from 'vs/base/node/profiler';

Expand All @@ -33,8 +32,8 @@ class StartupProfiler implements IWorkbenchContribution {
) {
// wait for everything to be ready
TPromise.join<any>([
lifecycleService.when(LifecyclePhase.Running),
extensionService.onReady(),
toPromise(filterEvent(lifecycleService.onDidChangePhase, phase => phase === LifecyclePhase.Running)),
]).then(() => {
this._stopProfiling();
});
Expand Down
Expand Up @@ -33,7 +33,6 @@ import { IWindowService } from 'vs/platform/windows/common/windows';
import { Action } from 'vs/base/common/actions';
import { IDisposable } from 'vs/base/common/lifecycle';
import { mark, time } from 'vs/base/common/performance';
import { toPromise, filterEvent } from 'vs/base/common/event';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';

const SystemExtensionsRoot = path.normalize(path.join(URI.parse(require.toUrl('')).fsPath, '..', 'extensions'));
Expand Down Expand Up @@ -100,12 +99,12 @@ export class ExtensionService implements IExtensionService {
this._extensionHostProcessCustomers = [];
this._extensionHostProcessProxy = null;

toPromise(filterEvent(lifecycleService.onDidChangePhase, phase => phase === LifecyclePhase.Running)).then(() => {
lifecycleService.when(LifecyclePhase.Restoring).then(() => {
// delay extension host creation and extension scanning
// until after the editors/panels are restored
this._startExtensionHostProcess([]);
this._scanAndHandleExtensions();
});
this._startExtensionHostProcess([]);
this._scanAndHandleExtensions();
}

public restartExtensionHost(): void {
Expand Down
Expand Up @@ -13,19 +13,21 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
import { ipcRenderer as ipc } from 'electron';
import Event, { Emitter } from 'vs/base/common/event';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { mark } from 'vs/base/common/performance';
import { Barrier } from 'vs/workbench/services/extensions/node/barrier';

export class LifecycleService implements ILifecycleService {

private static readonly _lastShutdownReasonKey = 'lifecyle.lastShutdownReason';

public _serviceBrand: any;

private readonly _onDidChangePhase = new Emitter<LifecyclePhase>();
private readonly _onWillShutdown = new Emitter<ShutdownEvent>();
private readonly _onShutdown = new Emitter<ShutdownReason>();
private readonly _startupKind: StartupKind;

private _phase: LifecyclePhase = LifecyclePhase.Starting;
private _phaseWhen = new Map<LifecyclePhase, Barrier>();

constructor(
@IMessageService private _messageService: IMessageService,
Expand All @@ -50,18 +52,36 @@ export class LifecycleService implements ILifecycleService {
}

public set phase(value: LifecyclePhase) {
if (this._phase !== value) {
this._phase = value;
this._onDidChangePhase.fire(value);
if (value < this.phase) {
throw new Error('Lifecycle cannot go backwards');
}
if (this._phase === value) {
return;
}

this._phase = value;
mark(`LifecyclePhase/${LifecyclePhase[value]}`);

if (this._phaseWhen.has(this._phase)) {
this._phaseWhen.get(this._phase).open();
this._phaseWhen.delete(this._phase);
}
}

public get startupKind(): StartupKind {
return this._startupKind;
public when(phase: LifecyclePhase): Thenable<any> {
if (phase <= this._phase) {
return Promise.resolve();
}
let barrier = this._phaseWhen.get(phase);
if (!barrier) {
barrier = new Barrier();
this._phaseWhen.set(phase, barrier);
}
return barrier.wait();
}

public get onDidChangePhase(): Event<LifecyclePhase> {
return this._onDidChangePhase.event;
public get startupKind(): StartupKind {
return this._startupKind;
}

public get onWillShutdown(): Event<ShutdownEvent> {
Expand Down
11 changes: 5 additions & 6 deletions src/vs/workbench/test/workbenchTestServices.ts
Expand Up @@ -60,6 +60,7 @@ import { ITextResourceConfigurationService } from 'vs/editor/common/services/res
import { IPosition } from 'vs/editor/common/core/position';
import { ICommandAction } from 'vs/platform/actions/common/actions';
import { IHashService } from 'vs/workbench/services/hash/common/hashService';
import { notImplemented } from 'vs/base/common/errors';

export function createFileInput(instantiationService: IInstantiationService, resource: URI): FileEditorInput {
return instantiationService.createInstance(FileEditorInput, resource, void 0);
Expand Down Expand Up @@ -1008,10 +1009,12 @@ export class TestLifecycleService implements ILifecycleService {
public phase: LifecyclePhase;
public startupKind: StartupKind;

private _onDidChangePhase = new Emitter<LifecyclePhase>();
private _onWillShutdown = new Emitter<ShutdownEvent>();
private _onShutdown = new Emitter<ShutdownReason>();

when(): Thenable<void> {
throw notImplemented();
};

public fireShutdown(reason = ShutdownReason.QUIT): void {
this._onShutdown.fire(reason);
Expand All @@ -1021,10 +1024,6 @@ export class TestLifecycleService implements ILifecycleService {
this._onWillShutdown.fire(event);
}

public get onDidChangePhase(): Event<LifecyclePhase> {
return this._onDidChangePhase.event;
}

public get onWillShutdown(): Event<ShutdownEvent> {
return this._onWillShutdown.event;
}
Expand Down Expand Up @@ -1250,4 +1249,4 @@ export class TestHashService implements IHashService {

export function getRandomTestPath(tmpdir: string, ...segments: string[]): string {
return paths.join(tmpdir, ...segments, generateUuid());
}
}

0 comments on commit ab17bb7

Please sign in to comment.