Skip to content

Commit ab17bb7

Browse files
committed
add a new lifecycle event Restoring which is set when the editors/viewlets are being restored (start). also in the lifecycle service replace onDidChangePhase with when
1 parent b94569f commit ab17bb7

8 files changed

Lines changed: 52 additions & 35 deletions

File tree

src/vs/platform/lifecycle/common/lifecycle.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,9 @@ export enum StartupKind {
4747

4848
export enum LifecyclePhase {
4949
Starting = 1,
50-
Running = 2,
51-
ShuttingDown = 3
50+
Restoring = 2,
51+
Running = 3,
52+
ShuttingDown = 4
5253
}
5354

5455
/**
@@ -70,9 +71,10 @@ export interface ILifecycleService {
7071
readonly phase: LifecyclePhase;
7172

7273
/**
73-
* An event that fire when the lifecycle phase has changed
74+
* Returns a promise that resolves when a certain lifecycle phase
75+
* has started.
7476
*/
75-
readonly onDidChangePhase: Event<LifecyclePhase>;
77+
when(phase: LifecyclePhase): Thenable<void>;
7678

7779
/**
7880
* Fired before shutdown happens. Allows listeners to veto against the
@@ -92,8 +94,8 @@ export interface ILifecycleService {
9294
export const NullLifecycleService: ILifecycleService = {
9395
_serviceBrand: null,
9496
phase: LifecyclePhase.Running,
97+
when() { return Promise.resolve(); },
9598
startupKind: StartupKind.NewWindow,
96-
onDidChangePhase: Event.None,
9799
onWillShutdown: Event.None,
98100
onShutdown: Event.None
99101
};
@@ -127,4 +129,4 @@ export function handleVetos(vetos: (boolean | TPromise<boolean>)[], onError: (er
127129
}
128130

129131
return TPromise.join(promises).then(() => lazyValue);
130-
}
132+
}

src/vs/workbench/common/editor/textEditorModel.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,7 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd
7070
protected createTextEditorModel(value: string | IRawTextSource, resource?: URI, modeId?: string): TPromise<EditorModel> {
7171
const firstLineText = this.getFirstLineText(value);
7272
const mode = this.getOrCreateMode(this.modeService, modeId, firstLineText);
73-
74-
// 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
75-
return TPromise.any<any>([TPromise.timeout(50), mode]).then(() => {
76-
return this.doCreateTextEditorModel(value, mode, resource);
77-
});
73+
return TPromise.as(this.doCreateTextEditorModel(value, mode, resource));
7874
}
7975

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

167163
super.dispose();
168164
}
169-
}
165+
}

src/vs/workbench/electron-browser/shell.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ export class WorkbenchShell {
165165
const [instantiationService, serviceCollection] = this.initServiceCollection(parent.getHTMLElement());
166166

167167
// Workbench
168-
this.workbench = instantiationService.createInstance(Workbench, parent.getHTMLElement(), workbenchContainer.getHTMLElement(), this.configuration, serviceCollection);
168+
this.workbench = instantiationService.createInstance(Workbench, parent.getHTMLElement(), workbenchContainer.getHTMLElement(), this.configuration, serviceCollection, this.lifecycleService);
169169
this.workbench.startup({
170170
onWorkbenchStarted: (info: IWorkbenchStartedInfo) => {
171171

src/vs/workbench/electron-browser/workbench.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ import { ProgressService2 } from 'vs/workbench/services/progress/browser/progres
7979
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
8080
import { ITextModelService } from 'vs/editor/common/services/resolverService';
8181
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
82-
import { ILifecycleService, ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle';
82+
import { ShutdownReason, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
83+
import { LifecycleService } from 'vs/workbench/services/lifecycle/electron-browser/lifecycleService';
8384
import { IWindowService, IWindowConfiguration as IWindowSettings, IWindowConfiguration, IPath } from 'vs/platform/windows/common/windows';
8485
import { IMessageService } from 'vs/platform/message/common/message';
8586
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
@@ -217,10 +218,10 @@ export class Workbench implements IPartService {
217218
container: HTMLElement,
218219
configuration: IWindowConfiguration,
219220
serviceCollection: ServiceCollection,
221+
private lifecycleService: LifecycleService,
220222
@IInstantiationService private instantiationService: IInstantiationService,
221223
@IWorkspaceContextService private contextService: IWorkspaceContextService,
222224
@IStorageService private storageService: IStorageService,
223-
@ILifecycleService private lifecycleService: ILifecycleService,
224225
@IMessageService private messageService: IMessageService,
225226
@IConfigurationService private configurationService: WorkspaceService,
226227
@ITelemetryService private telemetryService: ITelemetryService,
@@ -339,6 +340,7 @@ export class Workbench implements IPartService {
339340
const editorRestoreClock = time('restore:editors');
340341
const restoredEditors: string[] = [];
341342
compositeAndEditorPromises.push(this.resolveEditorsToOpen().then(inputs => {
343+
this.lifecycleService.phase = LifecyclePhase.Restoring;
342344
let editorOpenPromise: TPromise<IEditor[]>;
343345
if (inputs.length) {
344346
editorOpenPromise = this.editorService.openEditors(inputs.map(input => { return { input, position: EditorPosition.ONE }; }));

src/vs/workbench/parts/performance/electron-browser/performance.contribution.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import { ReportPerformanceIssueAction } from 'vs/workbench/electron-browser/acti
1717
import { TPromise } from 'vs/base/common/winjs.base';
1818
import { join } from 'path';
1919
import { localize } from 'vs/nls';
20-
import { toPromise, filterEvent } from 'vs/base/common/event';
2120
import { readdir } from 'vs/base/node/pfs';
2221
import { stopProfiling } from 'vs/base/node/profiler';
2322

@@ -33,8 +32,8 @@ class StartupProfiler implements IWorkbenchContribution {
3332
) {
3433
// wait for everything to be ready
3534
TPromise.join<any>([
35+
lifecycleService.when(LifecyclePhase.Running),
3636
extensionService.onReady(),
37-
toPromise(filterEvent(lifecycleService.onDidChangePhase, phase => phase === LifecyclePhase.Running)),
3837
]).then(() => {
3938
this._stopProfiling();
4039
});

src/vs/workbench/services/extensions/electron-browser/extensionService.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import { IWindowService } from 'vs/platform/windows/common/windows';
3333
import { Action } from 'vs/base/common/actions';
3434
import { IDisposable } from 'vs/base/common/lifecycle';
3535
import { mark, time } from 'vs/base/common/performance';
36-
import { toPromise, filterEvent } from 'vs/base/common/event';
3736
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
3837

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

103-
toPromise(filterEvent(lifecycleService.onDidChangePhase, phase => phase === LifecyclePhase.Running)).then(() => {
102+
lifecycleService.when(LifecyclePhase.Restoring).then(() => {
104103
// delay extension host creation and extension scanning
105104
// until after the editors/panels are restored
105+
this._startExtensionHostProcess([]);
106+
this._scanAndHandleExtensions();
106107
});
107-
this._startExtensionHostProcess([]);
108-
this._scanAndHandleExtensions();
109108
}
110109

111110
public restartExtensionHost(): void {

src/vs/workbench/services/lifecycle/electron-browser/lifecycleService.ts

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,21 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
1313
import { ipcRenderer as ipc } from 'electron';
1414
import Event, { Emitter } from 'vs/base/common/event';
1515
import { IWindowService } from 'vs/platform/windows/common/windows';
16+
import { mark } from 'vs/base/common/performance';
17+
import { Barrier } from 'vs/workbench/services/extensions/node/barrier';
1618

1719
export class LifecycleService implements ILifecycleService {
1820

1921
private static readonly _lastShutdownReasonKey = 'lifecyle.lastShutdownReason';
2022

2123
public _serviceBrand: any;
2224

23-
private readonly _onDidChangePhase = new Emitter<LifecyclePhase>();
2425
private readonly _onWillShutdown = new Emitter<ShutdownEvent>();
2526
private readonly _onShutdown = new Emitter<ShutdownReason>();
2627
private readonly _startupKind: StartupKind;
2728

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

3032
constructor(
3133
@IMessageService private _messageService: IMessageService,
@@ -50,18 +52,36 @@ export class LifecycleService implements ILifecycleService {
5052
}
5153

5254
public set phase(value: LifecyclePhase) {
53-
if (this._phase !== value) {
54-
this._phase = value;
55-
this._onDidChangePhase.fire(value);
55+
if (value < this.phase) {
56+
throw new Error('Lifecycle cannot go backwards');
57+
}
58+
if (this._phase === value) {
59+
return;
60+
}
61+
62+
this._phase = value;
63+
mark(`LifecyclePhase/${LifecyclePhase[value]}`);
64+
65+
if (this._phaseWhen.has(this._phase)) {
66+
this._phaseWhen.get(this._phase).open();
67+
this._phaseWhen.delete(this._phase);
5668
}
5769
}
5870

59-
public get startupKind(): StartupKind {
60-
return this._startupKind;
71+
public when(phase: LifecyclePhase): Thenable<any> {
72+
if (phase <= this._phase) {
73+
return Promise.resolve();
74+
}
75+
let barrier = this._phaseWhen.get(phase);
76+
if (!barrier) {
77+
barrier = new Barrier();
78+
this._phaseWhen.set(phase, barrier);
79+
}
80+
return barrier.wait();
6181
}
6282

63-
public get onDidChangePhase(): Event<LifecyclePhase> {
64-
return this._onDidChangePhase.event;
83+
public get startupKind(): StartupKind {
84+
return this._startupKind;
6585
}
6686

6787
public get onWillShutdown(): Event<ShutdownEvent> {

src/vs/workbench/test/workbenchTestServices.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import { ITextResourceConfigurationService } from 'vs/editor/common/services/res
6060
import { IPosition } from 'vs/editor/common/core/position';
6161
import { ICommandAction } from 'vs/platform/actions/common/actions';
6262
import { IHashService } from 'vs/workbench/services/hash/common/hashService';
63+
import { notImplemented } from 'vs/base/common/errors';
6364

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

1011-
private _onDidChangePhase = new Emitter<LifecyclePhase>();
10121012
private _onWillShutdown = new Emitter<ShutdownEvent>();
10131013
private _onShutdown = new Emitter<ShutdownReason>();
10141014

1015+
when(): Thenable<void> {
1016+
throw notImplemented();
1017+
};
10151018

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

1024-
public get onDidChangePhase(): Event<LifecyclePhase> {
1025-
return this._onDidChangePhase.event;
1026-
}
1027-
10281027
public get onWillShutdown(): Event<ShutdownEvent> {
10291028
return this._onWillShutdown.event;
10301029
}
@@ -1250,4 +1249,4 @@ export class TestHashService implements IHashService {
12501249

12511250
export function getRandomTestPath(tmpdir: string, ...segments: string[]): string {
12521251
return paths.join(tmpdir, ...segments, generateUuid());
1253-
}
1252+
}

0 commit comments

Comments
 (0)