From ebf608421d5aab2945c348eba5e8c8842dbd7f11 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Thu, 30 Jan 2025 18:42:54 +0300 Subject: [PATCH 1/3] Proper finalization --- .../arkui/src/generated/Finalizable.ts | 32 ------- interop/src/arkts/Finalizable.sts | 94 +++++++++++++++++-- interop/src/interop/Finalizable.ts | 3 +- 3 files changed, 87 insertions(+), 42 deletions(-) delete mode 100644 arkoala-arkts/arkui/src/generated/Finalizable.ts diff --git a/arkoala-arkts/arkui/src/generated/Finalizable.ts b/arkoala-arkts/arkui/src/generated/Finalizable.ts deleted file mode 100644 index 0b931ee06..000000000 --- a/arkoala-arkts/arkui/src/generated/Finalizable.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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. - */ - -import { pointer, nullptr } from "@koalaui/interop" - -export class Finalizable { - public ptr: pointer - public finalizerPtr: pointer - - constructor(ptr: pointer, finalizerPtr: pointer) { - this.ptr = ptr - this.finalizerPtr = finalizerPtr - } - - release(): pointer { - let result = this.ptr - this.ptr = nullptr - return result - } -} \ No newline at end of file diff --git a/interop/src/arkts/Finalizable.sts b/interop/src/arkts/Finalizable.sts index 50b494929..1bf66cf75 100644 --- a/interop/src/arkts/Finalizable.sts +++ b/interop/src/arkts/Finalizable.sts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 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 @@ -13,20 +13,98 @@ * limitations under the License. */ -import { pointer, nullptr } from "./InteropTypes" +import { finalizerRegister, finalizerUnregister, Thunk } from "@koalaui/common" +import { InteropNativeModule } from "./InteropNativeModule" +import { pointer } from "./InteropTypes" -export class Finalizable { - public ptr: pointer - public finalizerPtr: pointer +const nullptr: pointer = 0 + +export class NativeThunk implements Thunk { + finalizer: pointer + obj: pointer + name: string|undefined + + constructor(obj: pointer, finalizer: pointer, name?: string) { + this.finalizer = finalizer + this.obj = obj + this.name = name + } + + clean() { + if (this.obj != nullptr) { + this.destroyNative(this.obj, this.finalizer) + } + this.obj = nullptr + } - constructor(ptr: pointer, finalizerPtr: pointer) { + destroyNative(ptr: pointer, finalizer: pointer): void { + InteropNativeModule._InvokeFinalizer(ptr, finalizer) + } +} + +/** + * Class with the custom finalizer, usually used to release a native peer. + * Do not use directly, only via subclasses. + */ +export class Finalizable { + ptr: pointer + finalizer: pointer + cleaner: NativeThunk|undefined = undefined + managed: boolean + constructor(ptr: pointer, finalizer: pointer, managed: boolean = true) { this.ptr = ptr - this.finalizerPtr = finalizerPtr + this.finalizer = finalizer + this.managed = managed + const handle = this.createHandle() + + if (this.managed) { + if (this.ptr == nullptr) throw new Error("Can't have nullptr ptr ${}") + if (this.finalizer == nullptr) throw new Error("Managed finalizer is 0") + + const thunk = this.makeNativeThunk(ptr, finalizer, handle) + finalizerRegister(this, thunk) + this.cleaner = thunk + } + } + + createHandle(): string | undefined { + return undefined + } + + makeNativeThunk(ptr: pointer, finalizer: pointer, handle: string | undefined): NativeThunk { + return new NativeThunk(ptr, finalizer, handle) + } + + close() { + if (this.ptr == nullptr) { + throw new Error(`Closing a closed object: ` + this.toString()) + } else if (this.cleaner == undefined) { + throw new Error(`No thunk assigned to ` + this.toString()) + } else { + finalizerUnregister(this) + this.cleaner!.clean() + this.cleaner = undefined + this.ptr = nullptr + } } release(): pointer { + finalizerUnregister(this) + if (this.cleaner) + this.cleaner!.obj = nullptr let result = this.ptr this.ptr = nullptr return result } -} \ No newline at end of file + + resetPeer(pointer: pointer) { + if (this.managed) throw new Error("Can only reset peer for an unmanaged object") + this.ptr = pointer + } + + use(body: (value: Finalizable) => R): R { + let result = body(this) + this.close() + return result + } +} diff --git a/interop/src/interop/Finalizable.ts b/interop/src/interop/Finalizable.ts index 55af49291..5f2bcbe20 100644 --- a/interop/src/interop/Finalizable.ts +++ b/interop/src/interop/Finalizable.ts @@ -13,8 +13,7 @@ * limitations under the License. */ -import { Wrapper } from "./Wrapper" -import { nullptr, isNullPtr } from "./Wrapper" +import { Wrapper, nullptr, isNullPtr } from "./Wrapper" import { finalizerRegister, finalizerUnregister, Thunk } from "@koalaui/common" import { InteropNativeModule } from "./InteropNativeModule" import { pointer } from "./InteropTypes" -- Gitee From 7cb5354cb3c1fcbdbed4bfa7ee34ab314dcf5d98 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Thu, 30 Jan 2025 18:47:43 +0300 Subject: [PATCH 2/3] Compiles --- interop/src/arkts/Finalizable.sts | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/interop/src/arkts/Finalizable.sts b/interop/src/arkts/Finalizable.sts index 1bf66cf75..5e70dbed3 100644 --- a/interop/src/arkts/Finalizable.sts +++ b/interop/src/arkts/Finalizable.sts @@ -17,9 +17,9 @@ import { finalizerRegister, finalizerUnregister, Thunk } from "@koalaui/common" import { InteropNativeModule } from "./InteropNativeModule" import { pointer } from "./InteropTypes" -const nullptr: pointer = 0 +export const nullptr: pointer = 0 -export class NativeThunk implements Thunk { +class NativeThunk implements Thunk { finalizer: pointer obj: pointer name: string|undefined @@ -55,26 +55,18 @@ export class Finalizable { this.ptr = ptr this.finalizer = finalizer this.managed = managed - const handle = this.createHandle() + const handle = undefined if (this.managed) { if (this.ptr == nullptr) throw new Error("Can't have nullptr ptr ${}") if (this.finalizer == nullptr) throw new Error("Managed finalizer is 0") - const thunk = this.makeNativeThunk(ptr, finalizer, handle) + const thunk = new NativeThunk(ptr, finalizer, handle) finalizerRegister(this, thunk) this.cleaner = thunk } } - createHandle(): string | undefined { - return undefined - } - - makeNativeThunk(ptr: pointer, finalizer: pointer, handle: string | undefined): NativeThunk { - return new NativeThunk(ptr, finalizer, handle) - } - close() { if (this.ptr == nullptr) { throw new Error(`Closing a closed object: ` + this.toString()) -- Gitee From 79899108dddd3a236161bfa1eb44b1e85bcc2f58 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Thu, 30 Jan 2025 18:57:35 +0300 Subject: [PATCH 3/3] Simpler --- interop/src/arkts/Finalizable.sts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/interop/src/arkts/Finalizable.sts b/interop/src/arkts/Finalizable.sts index 5e70dbed3..6ae3ac2d8 100644 --- a/interop/src/arkts/Finalizable.sts +++ b/interop/src/arkts/Finalizable.sts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Copyright (c) 2025 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 @@ -15,9 +15,7 @@ import { finalizerRegister, finalizerUnregister, Thunk } from "@koalaui/common" import { InteropNativeModule } from "./InteropNativeModule" -import { pointer } from "./InteropTypes" - -export const nullptr: pointer = 0 +import { pointer, nullptr } from "./InteropTypes" class NativeThunk implements Thunk { finalizer: pointer -- Gitee