2
* Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3
* Licensed under the Apache License, Version 2.0 (the "License");
4
* you may not use this file except in compliance with the License.
5
* You may obtain a copy of the License at
7
* http://www.apache.org/licenses/LICENSE-2.0
9
* Unless required by applicable law or agreed to in writing, software
10
* distributed under the License is distributed on an "AS IS" BASIS,
11
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
* See the License for the specific language governing permissions and
13
* limitations under the License.
18
/** This interface represents an unique observer that can be notified that some changes. */
19
export interface Dependency {
20
/** Returns `true` if the dependency is no longer actual. */
21
readonly obsolete: boolean
23
/** Notifies the dependency that it should be invalidated. */
27
/** This class allows to store and update all dependencies. */
28
export class Dependencies {
30
private dependencies: Set<Dependency> | undefined = undefined
31
private latest: Dependency | undefined = undefined
33
/** Returns `true` if there are no dependencies to invalidate. */
34
get empty(): boolean {
35
return this.dependencies !== undefined
36
? this.dependencies!.size == 0
37
: this.latest === undefined
40
/** @param dependency - a dependency to invalidate */
41
register(dependency?: Dependency): void {
42
if (dependency === undefined || dependency == this.latest || dependency.obsolete) return
43
if (this.dependencies !== undefined) {
44
this.dependencies!.add(dependency)
45
} else if (this.latest !== undefined) {
46
this.dependencies = new Set<Dependency>()
47
this.dependencies!.add(this.latest!)
48
this.dependencies!.add(dependency)
50
this.latest = dependency
53
/** Invalidates all dependencies and removes obsolete ones. */
54
updateDependencies(invalidate: boolean): void {
55
if (++this.frame < SKIP_FRAMES && !invalidate) return
57
if (this.dependencies !== undefined) {
58
let disposed: Array<Dependency> | undefined = undefined
59
const it = this.dependencies!.keys()
61
const result = it.next()
62
if (result.done) break
63
const dependency = result.value as Dependency
64
if (!updateDependency(invalidate, dependency)) {
66
disposed.push(dependency)
68
disposed = Array.of<Dependency>(dependency)
73
let index = disposed.length
74
while (0 < index--) this.dependencies!.delete(disposed[index])
76
} else if (this.latest !== undefined && !updateDependency(invalidate, this.latest!)) {
77
this.latest = undefined
82
function updateDependency(invalidate: boolean, dependency: Dependency): boolean {
83
if (dependency.obsolete) return false
84
if (invalidate) dependency.invalidate()