diff --git a/discojs/discojs-web/src/dataset/data_loader/cache.ts b/discojs/discojs-web/src/dataset/data_loader/cache.ts new file mode 100644 index 000000000..a2fc3e9b5 --- /dev/null +++ b/discojs/discojs-web/src/dataset/data_loader/cache.ts @@ -0,0 +1,60 @@ +export class Deferred { + promise: Promise = new Promise(() => {}) + resolve: (value: T | PromiseLike) => void = () => {} + reject: (reason?: any) => void = () => {} + + constructor() { + this.reset() + } + + reset() { + this.promise = new Promise((resolve, reject) => { + this.resolve = resolve + this.reject = reject + }) + } +} + +export class Cache { + position: number = 0 + private readonly cache: Deferred[] + + private constructor( + readonly length: number, + private readonly request: ( + pos: number, + init?: boolean + ) => void | Promise + ) { + this.cache = Array.from({ length }, () => new Deferred()) + } + + // pre-loads the cache with the first n requests + static async init( + length: number, + request: (pos: number, init?: boolean) => void | Promise, + initializer: (c: Cache) => void + ): Promise> { + const cache = new Cache(length, request) + initializer(cache) + for (let pos = 0; pos < length; pos++) { + cache.request(pos, true) + } + return cache + } + + put(pos: number, elt: E): void { + const promise = this.cache[pos] as Deferred + promise.resolve(elt) + } + + async next(): Promise { + const eltOrDeffered = this.cache[this.position] + const elt = await eltOrDeffered.promise + const pos = this.position + this.cache[pos] = new Deferred() + this.request(pos) + this.position = (pos + 1) % this.length + return elt + } +}