Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/base/common/cache.ts
3291 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { CancellationToken, CancellationTokenSource } from './cancellation.js';
7
import { IDisposable } from './lifecycle.js';
8
9
export interface CacheResult<T> extends IDisposable {
10
promise: Promise<T>;
11
}
12
13
export class Cache<T> {
14
15
private result: CacheResult<T> | null = null;
16
constructor(private task: (ct: CancellationToken) => Promise<T>) { }
17
18
get(): CacheResult<T> {
19
if (this.result) {
20
return this.result;
21
}
22
23
const cts = new CancellationTokenSource();
24
const promise = this.task(cts.token);
25
26
this.result = {
27
promise,
28
dispose: () => {
29
this.result = null;
30
cts.cancel();
31
cts.dispose();
32
}
33
};
34
35
return this.result;
36
}
37
}
38
39
export function identity<T>(t: T): T {
40
return t;
41
}
42
43
interface ICacheOptions<TArg> {
44
/**
45
* The cache key is used to identify the cache entry.
46
* Strict equality is used to compare cache keys.
47
*/
48
getCacheKey: (arg: TArg) => unknown;
49
}
50
51
/**
52
* Uses a LRU cache to make a given parametrized function cached.
53
* Caches just the last key/value.
54
*/
55
export class LRUCachedFunction<TArg, TComputed> {
56
private lastCache: TComputed | undefined = undefined;
57
private lastArgKey: unknown | undefined = undefined;
58
59
private readonly _fn: (arg: TArg) => TComputed;
60
private readonly _computeKey: (arg: TArg) => unknown;
61
62
constructor(fn: (arg: TArg) => TComputed);
63
constructor(options: ICacheOptions<TArg>, fn: (arg: TArg) => TComputed);
64
constructor(arg1: ICacheOptions<TArg> | ((arg: TArg) => TComputed), arg2?: (arg: TArg) => TComputed) {
65
if (typeof arg1 === 'function') {
66
this._fn = arg1;
67
this._computeKey = identity;
68
} else {
69
this._fn = arg2!;
70
this._computeKey = arg1.getCacheKey;
71
}
72
}
73
74
public get(arg: TArg): TComputed {
75
const key = this._computeKey(arg);
76
if (this.lastArgKey !== key) {
77
this.lastArgKey = key;
78
this.lastCache = this._fn(arg);
79
}
80
return this.lastCache!;
81
}
82
}
83
84
/**
85
* Uses an unbounded cache to memoize the results of the given function.
86
*/
87
export class CachedFunction<TArg, TComputed> {
88
private readonly _map = new Map<TArg, TComputed>();
89
private readonly _map2 = new Map<unknown, TComputed>();
90
public get cachedValues(): ReadonlyMap<TArg, TComputed> {
91
return this._map;
92
}
93
94
private readonly _fn: (arg: TArg) => TComputed;
95
private readonly _computeKey: (arg: TArg) => unknown;
96
97
constructor(fn: (arg: TArg) => TComputed);
98
constructor(options: ICacheOptions<TArg>, fn: (arg: TArg) => TComputed);
99
constructor(arg1: ICacheOptions<TArg> | ((arg: TArg) => TComputed), arg2?: (arg: TArg) => TComputed) {
100
if (typeof arg1 === 'function') {
101
this._fn = arg1;
102
this._computeKey = identity;
103
} else {
104
this._fn = arg2!;
105
this._computeKey = arg1.getCacheKey;
106
}
107
}
108
109
public get(arg: TArg): TComputed {
110
const key = this._computeKey(arg);
111
if (this._map2.has(key)) {
112
return this._map2.get(key)!;
113
}
114
115
const value = this._fn(arg);
116
this._map.set(arg, value);
117
this._map2.set(key, value);
118
return value;
119
}
120
}
121
122