src/vs/editor/contrib/documentSymbols/browser/outlineModel.ts/OutlineModelService/getOrCreate
class OutlineModelService:	async getOrCreate(textModel: ITextModel, token: CancellationToken): Promise<OutlineModel> {

		const registry = this._languageFeaturesService.documentSymbolProvider;
		const provider = registry.ordered(textModel);

		let data = this._cache.get(textModel.id);
		if (!data || data.versionId !== textModel.getVersionId() || !equals(data.provider, provider)) {
			let source = new CancellationTokenSource();
			data = {
				versionId: textModel.getVersionId(),
				provider,
				promiseCnt: 0,
				source,
				promise: OutlineModel.create(registry, textModel, source.token),
				model: undefined,
			};
			this._cache.set(textModel.id, data);

			const now = Date.now();
			data.promise.then(outlineModel => {
				data!.model = outlineModel;
				this._debounceInformation.update(textModel, Date.now() - now);
			}).catch(_err => {
				this._cache.delete(textModel.id);
			});
		}

		if (data.model) {
			// resolved -> return data
			return data.model;
		}

		// increase usage counter
		data.promiseCnt += 1;

		const listener = token.onCancellationRequested(() => {
			// last -> cancel provider request, remove cached promise
			if (--data!.promiseCnt === 0) {
				data!.source.cancel();
				this._cache.delete(textModel.id);
			}
		});

		try {
			return await data.promise;
		} finally {
			listener.dispose();
		}
	}