diff --git a/incremental/runtime/src/states/Journal.ts b/incremental/runtime/src/states/Journal.ts new file mode 100644 index 0000000000000000000000000000000000000000..b9b308a7feceeb835472f7723a3bcefe8c2f5943 --- /dev/null +++ b/incremental/runtime/src/states/Journal.ts @@ -0,0 +1,90 @@ +import { MutableState, State } from "./State"; + +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class JournalRecord { + constructor(public value: Object, public state: State) {} +} + +export interface Journal { + set(state: State, value: T): void + get(state: State): T + play(): void +} + +export interface Store { + get(state: State): T + set(state: State, value: T): void +} + +class WeakStore { + private store = new WeakMap, Object>() + set(state: State, value: T): void { + this.store.set(state as State, value as Object) + } + get(state: State): T { + return this.store.get(state as State) as T + } +} + +let store = new WeakStore() + +// We keep ordering with this data structure, but get/set is slower. +export class ArrayJournal implements Journal { + private log: Array = [] + set(state: State, value: T): void { + this.log.push(new JournalRecord(value as Object, state as State)) + } + get(state: State): T { + for (let i = this.log.length - 1; i >= 0; i--) { + if (this.log[i].state === state) { + console.log(`in journal at ${i}`) + return this.log[i].value as T + } + } + return store.get(state) + } + play(): void { + console.log(`play ${this.log.length} ops`) + for (let i = 0; i < this.log.length; i++) { + store.set(this.log[i].state, this.log[i].value) + } + this.log.splice(0, this.log.length) + } +} + +// We lose ordering with this data structure, but get/set is faster. +export class MapJournal implements Journal { + private log = new Map, Object>() + set(state: State, value: T): void { + this.log.set(state as State, value as Object) + } + get(state: State): T { + // Separate has/get as undefined is legit value for the state. + if (this.log.has(state as State)) { + console.log(`in journal`) + return this.log.get(state as State) as T + } else { + return store.get(state) + } + } + play(): void { + console.log(`play ${this.log.size} ops`) + for (let [state, value] of this.log) { + store.set(state, value) + } + this.log.clear() + } +} \ No newline at end of file diff --git a/incremental/runtime/src/states/State.ts b/incremental/runtime/src/states/State.ts index bf6b8c1c9986cfbb86076ac8c5f2cc1abbefef93..7b3b4ceb421ac31568e2d863527050cc92736e70 100644 --- a/incremental/runtime/src/states/State.ts +++ b/incremental/runtime/src/states/State.ts @@ -19,6 +19,7 @@ import { Disposable, disposeContent, disposeContentBackward } from "./Disposable import { Observable, ObservableHandler } from "./Observable" import { IncrementalNode } from "../tree/IncrementalNode" import { ReadonlyTreeNode } from "../tree/ReadonlyTreeNode" +import { MapJournal } from "./Journal" export const CONTEXT_ROOT_SCOPE = "ohos.koala.context.root.scope" export const CONTEXT_ROOT_NODE = "ohos.koala.context.root.node" @@ -378,6 +379,7 @@ class StateManagerImpl implements StateManager { private readonly statesNamed = new Map() private readonly statesCreated = new Set() private readonly dirtyScopes = new Set() + journal = new MapJournal() current: ManagedScope | undefined = undefined external: Dependency | undefined = undefined updateNeeded = false