Convert cache to Disposable
This commit is contained in:
@@ -1182,32 +1182,52 @@ describe('Buffer', () => {
|
||||
});
|
||||
|
||||
describe('line string cache cleanup', () => {
|
||||
it('should clear shared cache entries with a single timer', async () => {
|
||||
buffer.fillViewportRows();
|
||||
buffer.lines.get(0)!.setCell(0, createCellData(0, 'a', 1));
|
||||
buffer.lines.get(1)!.setCell(0, createCellData(0, 'b', 1));
|
||||
it('should clear shared cache entries with a single timer', () => {
|
||||
const originalSetTimeout = globalThis.setTimeout;
|
||||
const originalClearTimeout = globalThis.clearTimeout;
|
||||
let timeoutId = 0;
|
||||
const scheduledTimeouts = new Map<number, () => void>();
|
||||
(globalThis as any).setTimeout = ((handler: (...args: any[]) => void) => {
|
||||
const id = ++timeoutId;
|
||||
scheduledTimeouts.set(id, () => handler());
|
||||
return id as ReturnType<typeof setTimeout>;
|
||||
}) as typeof setTimeout;
|
||||
(globalThis as any).clearTimeout = ((id: ReturnType<typeof setTimeout>) => {
|
||||
scheduledTimeouts.delete(id as unknown as number);
|
||||
}) as typeof clearTimeout;
|
||||
try {
|
||||
buffer.fillViewportRows();
|
||||
buffer.lines.get(0)!.setCell(0, createCellData(0, 'a', 1));
|
||||
buffer.lines.get(1)!.setCell(0, createCellData(0, 'b', 1));
|
||||
|
||||
assert.equal(buffer.translateBufferLineToString(0, false), `a${' '.repeat(INIT_COLS - 1)}`);
|
||||
assert.equal(buffer.translateBufferLineToString(1, false), `b${' '.repeat(INIT_COLS - 1)}`);
|
||||
assert.equal(buffer.translateBufferLineToString(0, false), `a${' '.repeat(INIT_COLS - 1)}`);
|
||||
assert.equal(buffer.translateBufferLineToString(1, false), `b${' '.repeat(INIT_COLS - 1)}`);
|
||||
|
||||
const cache = (buffer as any)._stringCache;
|
||||
assert.equal(cache.entries.size, 2);
|
||||
const previousTimer = (cache as any)._clearTimeout;
|
||||
assert.notEqual(previousTimer, undefined);
|
||||
const cache = (buffer as any)._stringCache;
|
||||
assert.equal(cache.entries.size, 2);
|
||||
const previousTimer = (cache as any)._clearTimeout.value;
|
||||
assert.notEqual(previousTimer, undefined);
|
||||
|
||||
// Another translation should refresh the same shared timer, not create a second queue.
|
||||
assert.equal(buffer.translateBufferLineToString(0, false), `a${' '.repeat(INIT_COLS - 1)}`);
|
||||
assert.notEqual((cache as any)._clearTimeout, undefined);
|
||||
assert.notEqual((cache as any)._clearTimeout, previousTimer);
|
||||
// Another translation should refresh the same shared timer, not create a second queue.
|
||||
assert.equal(buffer.translateBufferLineToString(0, false), `a${' '.repeat(INIT_COLS - 1)}`);
|
||||
assert.notEqual((cache as any)._clearTimeout.value, undefined);
|
||||
assert.notEqual((cache as any)._clearTimeout.value, previousTimer);
|
||||
|
||||
await new Promise(r => setTimeout(r, 70));
|
||||
for (const timeout of scheduledTimeouts.values()) {
|
||||
timeout();
|
||||
}
|
||||
scheduledTimeouts.clear();
|
||||
|
||||
assert.equal(cache.entries.size, 0);
|
||||
assert.equal((cache as any)._clearTimeout, undefined);
|
||||
assert.equal(cache.entries.size, 0);
|
||||
assert.equal((cache as any)._clearTimeout.value, undefined);
|
||||
|
||||
// Cache entries should be recreated lazily after a timer-based reset.
|
||||
assert.equal(buffer.translateBufferLineToString(0, false), `a${' '.repeat(INIT_COLS - 1)}`);
|
||||
assert.equal(cache.entries.size, 1);
|
||||
// Cache entries should be recreated lazily after a timer-based reset.
|
||||
assert.equal(buffer.translateBufferLineToString(0, false), `a${' '.repeat(INIT_COLS - 1)}`);
|
||||
assert.equal(cache.entries.size, 1);
|
||||
} finally {
|
||||
globalThis.setTimeout = originalSetTimeout;
|
||||
globalThis.clearTimeout = originalClearTimeout;
|
||||
}
|
||||
});
|
||||
|
||||
it('should reset line string cache state on clear and resize', () => {
|
||||
@@ -1217,11 +1237,11 @@ describe('Buffer', () => {
|
||||
|
||||
const cache = (buffer as any)._stringCache;
|
||||
assert.equal(cache.entries.size, 1);
|
||||
assert.notEqual((cache as any)._clearTimeout, undefined);
|
||||
assert.notEqual((cache as any)._clearTimeout.value, undefined);
|
||||
|
||||
buffer.clear();
|
||||
assert.equal(cache.entries.size, 0);
|
||||
assert.equal((cache as any)._clearTimeout, undefined);
|
||||
assert.equal((cache as any)._clearTimeout.value, undefined);
|
||||
|
||||
buffer.fillViewportRows();
|
||||
buffer.lines.get(0)!.setCell(0, createCellData(0, 'b', 1));
|
||||
@@ -1230,7 +1250,7 @@ describe('Buffer', () => {
|
||||
|
||||
buffer.resize(INIT_COLS - 1, INIT_ROWS);
|
||||
assert.equal(cache.entries.size, 0);
|
||||
assert.equal((cache as any)._clearTimeout, undefined);
|
||||
assert.equal((cache as any)._clearTimeout.value, undefined);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -5,14 +5,22 @@
|
||||
|
||||
import type { IBufferLineStringCache, IBufferLineStringCacheEntry } from 'common/buffer/BufferLine';
|
||||
import { disposableTimeout } from 'common/Async';
|
||||
import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
|
||||
import type { IDisposable } from 'common/Lifecycle';
|
||||
|
||||
const STRING_CACHE_CLEAR_DELAY_MS = 50;
|
||||
const enum Constants {
|
||||
CacheTtlMs = 15000
|
||||
}
|
||||
|
||||
export class BufferLineStringCache implements IBufferLineStringCache, IDisposable {
|
||||
export class BufferLineStringCache extends Disposable implements IBufferLineStringCache {
|
||||
public generation: number = 0;
|
||||
public readonly entries: Set<IBufferLineStringCacheEntry> = new Set();
|
||||
private _clearTimeout: IDisposable | undefined;
|
||||
private readonly _clearTimeout = this._register(new MutableDisposable<IDisposable>());
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._register(toDisposable(() => this.entries.clear()));
|
||||
}
|
||||
|
||||
public touch(): void {
|
||||
this._scheduleClear();
|
||||
@@ -30,8 +38,7 @@ export class BufferLineStringCache implements IBufferLineStringCache, IDisposabl
|
||||
}
|
||||
|
||||
public clear(): void {
|
||||
this._clearTimeout?.dispose();
|
||||
this._clearTimeout = undefined;
|
||||
this._clearTimeout.clear();
|
||||
this.generation++;
|
||||
for (const entry of this.entries) {
|
||||
entry.value = undefined;
|
||||
@@ -40,15 +47,10 @@ export class BufferLineStringCache implements IBufferLineStringCache, IDisposabl
|
||||
this.entries.clear();
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.clear();
|
||||
}
|
||||
|
||||
private _scheduleClear(): void {
|
||||
this._clearTimeout?.dispose();
|
||||
this._clearTimeout = disposableTimeout(() => {
|
||||
this._clearTimeout = undefined;
|
||||
this._clearTimeout.value = disposableTimeout(() => {
|
||||
this._clearTimeout.clear();
|
||||
this.clear();
|
||||
}, STRING_CACHE_CLEAR_DELAY_MS);
|
||||
}, Constants.CacheTtlMs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,13 +91,13 @@ describe('BufferSet', () => {
|
||||
|
||||
const oldCache = oldNormal._stringCache;
|
||||
assert.equal(oldCache.entries.size, 1);
|
||||
assert.notEqual(oldCache._clearTimeout, undefined);
|
||||
assert.notEqual(oldCache._clearTimeout.value, undefined);
|
||||
|
||||
bufferSet.reset();
|
||||
|
||||
assert.notEqual(bufferSet.normal, oldNormal);
|
||||
assert.equal(oldCache.entries.size, 0);
|
||||
assert.equal(oldCache._clearTimeout, undefined);
|
||||
assert.equal(oldCache._clearTimeout.value, undefined);
|
||||
});
|
||||
|
||||
it('should dispose both buffers when disposed', () => {
|
||||
@@ -112,15 +112,15 @@ describe('BufferSet', () => {
|
||||
|
||||
const normalCache = normal._stringCache;
|
||||
const altCache = alt._stringCache;
|
||||
assert.notEqual(normalCache._clearTimeout, undefined);
|
||||
assert.notEqual(altCache._clearTimeout, undefined);
|
||||
assert.notEqual(normalCache._clearTimeout.value, undefined);
|
||||
assert.notEqual(altCache._clearTimeout.value, undefined);
|
||||
|
||||
bufferSet.dispose();
|
||||
|
||||
assert.equal(normalCache.entries.size, 0);
|
||||
assert.equal(altCache.entries.size, 0);
|
||||
assert.equal(normalCache._clearTimeout, undefined);
|
||||
assert.equal(altCache._clearTimeout, undefined);
|
||||
assert.equal(normalCache._clearTimeout.value, undefined);
|
||||
assert.equal(altCache._clearTimeout.value, undefined);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user