UNPKG

@itwin/core-frontend

Version:
118 lines 4.35 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module Utils */ import { ReadonlySortedArray, SortedArray } from "@itwin/core-bentley"; /** An immutable set of [[TileUser]]s wherein uniqueness is determined by each TileUser's unique integer identifier. * @see [[UniqueTileUserSets]]. */ export class ReadonlyTileUserSet extends ReadonlySortedArray { constructor(user) { super((lhs, rhs) => lhs.tileUserId - rhs.tileUserId); if (undefined !== user) this._array.push(user); } } class TileUserSet extends ReadonlyTileUserSet { copyFrom(src) { this._array.length = src.length; let i = 0; for (const user of src) this._array[i++] = user; } clone() { const clone = new TileUserSet(); clone.copyFrom(this); return clone; } insert(user) { return this._insert(user); } remove(user) { return this._remove(user); } clear() { this._clear(); } } function compareTileUserSets(lhs, rhs) { if (lhs === rhs) return 0; let diff = lhs.length - rhs.length; if (0 === diff) { for (let i = 0; i < lhs.length; i++) { // lhs and rhs are the same length, and i is guaranteed to be in bounds for both. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion diff = lhs.get(i).tileUserId - rhs.get(i).tileUserId; if (0 !== diff) break; } } return diff; } const emptySet = new ReadonlyTileUserSet(); const scratchSet = new TileUserSet(); class TileUserSetSet extends SortedArray { constructor() { super((lhs, rhs) => compareTileUserSets(lhs, rhs)); } getForUser(user) { for (let i = 0; i < this.length; i++) { const set = this._array[i]; // If 1 === set.length, set.get(0) is guaranteed to be defined. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (1 === set.length && set.get(0) === user) return set; } const newSet = new TileUserSet(user); this.insert(newSet); return newSet; } getTileUserSet(user, users) { if (undefined === users || users.isEmpty) return this.getForUser(user); // Use the scratch set for equality comparison - only allocate if no equivalent set already exists. const toFind = scratchSet; toFind.copyFrom(users); toFind.insert(user); const found = this.findEqual(toFind); if (undefined !== found) { toFind.clear(); return found; } const newSet = toFind.clone(); toFind.clear(); this.insert(newSet); return newSet; } clearAll() { this.forEach((set) => set.clear()); this.clear(); } forgetUser(user) { for (const set of this) set.remove(user); } } /** Maintains a set of [[TileUserSets]] designed to minimize duplication. * For example, the tile request scheduler needs to associate with each [[TileRequest]] the set of [[TileUser]]s awaiting the request's response. * Using UniqueTileUserSets ensures all tiles requested by the same user use the same TileUserSet object. * Additionally, whenever a user is unregistered there is no need to track down every associated tile request - the user can just be removed from the TileUserSets managed by this object. * The TileUserSets managed by this object should be treated as immutable - "adding" a user to an existing set should be done using [[getTileUserSet]]. */ export class UniqueTileUserSets { _sets = new TileUserSetSet(); getTileUserSet(user, users) { return this._sets.getTileUserSet(user, users); } clearAll() { this._sets.clearAll(); } clear() { this._sets.clear(); } remove(user) { this._sets.forgetUser(user); } static get emptySet() { return emptySet; } } //# sourceMappingURL=TileUserSet.js.map