idlize
120 строк · 3.7 Кб
1/*
2* Copyright (c) 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
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
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.
14*/
15
16import { pointer, nullptr, isNullPtr } from "@koalaui/interop"17import { finalizerRegister, finalizerUnregister, Thunk } from "./Finalization";18import { nativeModule } from "@koalaui/arkoala";19
20export abstract class FinalizableBase {21ptr: pointer22finalizer: pointer23managed: boolean24cleaner?: NativeThunk = undefined25
26constructor(ptr: pointer, finalizer: pointer, managed: boolean) {27this.ptr = ptr28this.finalizer = finalizer29this.managed = managed30
31if (this.managed) {32if (isNullPtr(this.ptr)) throw new Error("Can't have nullptr ptr")33if (isNullPtr(this.finalizer)) throw new Error("Can't have nullptr finalizer")34
35const handle = this.createHandle()36const thunk = this.makeNativeThunk(ptr, finalizer, handle)37finalizerRegister(this, thunk)38this.cleaner = thunk39}40}41
42abstract makeNativeThunk(ptr: pointer, finalizer: pointer, handle: string|undefined): NativeThunk43
44createHandle(): string | undefined {45return undefined46}47
48close() {49if (isNullPtr(this.ptr)) {50throw new Error(`Closing a closed object: ${this}`)51} else if (this.cleaner === undefined || isNullPtr(this.cleaner.ptr) || isNullPtr(this.cleaner.finalizer)) {52throw new Error(`No thunk assigned to ${this}`)53}54
55finalizerUnregister(this)56this.cleaner?.clean()57this.cleaner = undefined58this.ptr = nullptr59}60
61release(): pointer {62finalizerUnregister(this)63if (this.cleaner !== undefined)64this.cleaner.ptr = nullptr65const result = this.ptr66this.ptr = nullptr67return result68}69
70resetPeer(pointer: pointer) {71if (this.managed) throw Error(`Can only reset peer for an unmanaged object`)72this.ptr = pointer73}74
75use<R>(body: (value: FinalizableBase) => R): R {76const result = body(this)77this.close()78return result79}80}
81
82export class Finalizable extends FinalizableBase {83constructor(public ptr: pointer, finalizer: pointer, managed: boolean = true) {84super(ptr, finalizer, managed)85}86
87makeNativeThunk(ptr: pointer, finalizer: pointer, handle: string | undefined): NativeThunk {88return new NativeThunkImpl(ptr, finalizer, handle)89}90}
91
92export abstract class NativeThunk implements Thunk {93ptr:pointer94finalizer: pointer95name?: string96
97constructor(ptr: pointer, finalizer: pointer, name?: string) {98this.ptr = ptr;99this.finalizer = finalizer;100this.name = name101}102
103clean() {104if(!isNullPtr(this.ptr)) {105this.destroyNative(this.ptr, this.finalizer)106}107this.ptr = nullptr;108}109
110abstract destroyNative(ptr: pointer, finalizer: pointer) : void111}
112
113class NativeThunkImpl extends NativeThunk {114constructor(ptr: pointer, finalizer: pointer, name?: string) {115super(ptr, finalizer, name)116}117destroyNative(ptr: pointer, finalizer: pointer): void {118nativeModule()._InvokeFinalizer(ptr, finalizer)119}120}
121