LifetimeSlot.ts
60 lines
| 1.6 KiB
| video/mp2t
|
TypeScriptLexer
|
|
r15 | import { ILifetimeSlot } from "../typings/interfaces"; | |
| import { isDestroyable } from "./traits"; | |||
| const _destroy = (item: unknown) => () => isDestroyable(item) && item.destroy(); | |||
| enum State { | |||
| New, | |||
| Initialized, | |||
| Destroyed | |||
| } | |||
| export class LifetimeSlot<T> implements ILifetimeSlot<T> { | |||
| private _value: NonNullable<T> | undefined = undefined; | |||
| private _state = State.New; | |||
| cleanup: () => void; | |||
| readonly remove: () => void; | |||
| constructor(remove: () => void) { | |||
| this.remove = this._finalizer(remove); | |||
| this.cleanup = this._finalizer(() => { }); | |||
| } | |||
| has(): boolean { | |||
| this._assertNotDisposed(); | |||
| return this._value !== undefined; | |||
| } | |||
| get(): NonNullable<T> { | |||
| this._assertNotDisposed(); | |||
| if (this._value === undefined) | |||
| throw new Error("The slot doesn't have a value"); | |||
| return this._value; | |||
| } | |||
| initialize(): boolean { | |||
| return this._state === State.New ? | |||
| (this._state = State.Initialized, true) : | |||
| false; | |||
| } | |||
| store(item: NonNullable<T>, cleanup: ((item: NonNullable<T>) => void) | undefined = _destroy): void { | |||
| this._assertNotDisposed(); | |||
| this._value = item; | |||
| if (cleanup) | |||
| this.cleanup = this._finalizer(() => cleanup(item)); | |||
| } | |||
| private _finalizer(cb: () => void) { | |||
| return () => this._state !== State.Destroyed ? (this._state = State.Destroyed, cb()) : void (0); | |||
| } | |||
| private _assertNotDisposed() { | |||
| if (this._state === State.Destroyed) | |||
| throw new Error("The slot is disposed"); | |||
| } | |||
| } |
