@itwin/core-frontend
Version:
iTwin.js frontend components
118 lines • 4.35 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* 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