From bd95f9c46abeafe42ebadf43fc70500e0af2267d Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Wed, 20 May 2026 19:00:22 +0900 Subject: [PATCH] Rework the cleanup a little bit so that we avoid the atomic boolean The atomic boolean was one extra heap allocation which we now avoid -- we just create one cleanup and inside it have an int, rather than creating the Bool separately and passing it to the cleanup. AFAICS this will avoid one alloc, which isn't much, but can add up since we do it for every wrapped swift object. This keeps semantics added by @sidepelican in https://github.com/swiftlang/swift-java/pull/760 just avoids the one heap alloc per SwiftInstance --- ...t2JavaGenerator+JavaBindingsPrinting.swift | 10 +++---- .../swiftkit/core/AutoSwiftMemorySession.java | 2 +- .../core/ConfinedSwiftMemorySession.java | 2 +- .../swift/swiftkit/core/JNISwiftInstance.java | 12 +++++---- .../core/JNISwiftInstanceCleanup.java | 19 ++++++++++---- .../swift/swiftkit/core/SwiftInstance.java | 22 ++++++---------- .../swiftkit/core/SwiftInstanceCleanup.java | 10 ++++++- .../core/collections/SwiftDictionaryMap.java | 8 +++--- .../swiftkit/core/collections/SwiftSet.java | 8 +++--- .../org/swift/swiftkit/AutoArenaTest.java | 14 +++++----- .../ffm/AllocatingAutoSwiftMemorySession.java | 2 +- .../swiftkit/ffm/FFMSwiftErrorInstance.java | 19 +++++--------- .../swift/swiftkit/ffm/FFMSwiftInstance.java | 26 +++---------------- .../swiftkit/ffm/FFMSwiftInstanceCleanup.java | 21 ++++++++++----- .../org/swift/swiftkit/ffm/AutoArenaTest.java | 6 ++--- .../JNI/JNIClassTests.swift | 2 +- .../JExtractSwiftTests/JNI/JNIEnumTests.swift | 2 +- .../JNI/JNIModuleTests.swift | 1 - .../JNI/JNIStructTests.swift | 1 + 19 files changed, 91 insertions(+), 96 deletions(-) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 0b0fb8dc3..ff114b228 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -27,7 +27,6 @@ extension JNISwift2JavaGenerator { "org.swift.swiftkit.core.util.*", "org.swift.swiftkit.core.collections.*", "java.util.*", - "java.util.concurrent.atomic.AtomicBoolean", // NonNull, Unsigned and friends "org.swift.swiftkit.core.annotations.*", @@ -282,6 +281,7 @@ extension JNISwift2JavaGenerator { } printer.print( """ + this.$cleanup = $createCleanup(); // Only register once we have fully initialized the object since this will need the object pointer. swiftArena.register(this); @@ -317,16 +317,16 @@ extension JNISwift2JavaGenerator { /** Pointer to the "self". */ private final long selfPointer; - /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */ - private final AtomicBoolean $state$destroyed = new AtomicBoolean(false); + /** Tracks whether this instance has been destroyed; doubles as the destroyed-state holder. */ + private final SwiftInstanceCleanup $cleanup; public long $memoryAddress() { return this.selfPointer; } @Override - public AtomicBoolean $statusDestroyedFlag() { - return $state$destroyed; + public SwiftInstanceCleanup $cleanup() { + return $cleanup; } """ ) diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/AutoSwiftMemorySession.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/AutoSwiftMemorySession.java index 36e732097..3d3d50964 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/AutoSwiftMemorySession.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/AutoSwiftMemorySession.java @@ -50,7 +50,7 @@ public void register(SwiftInstance instance) { // We make sure we don't capture `instance` in the // cleanup action, so we can ignore the warning below. - var cleanupAction = instance.$createCleanup(); + var cleanupAction = instance.$cleanup(); swiftCleaner.register(instance, cleanupAction); } } \ No newline at end of file diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java index 3514d9c16..7363539c2 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java @@ -54,7 +54,7 @@ public void close() { public void register(SwiftInstance instance) { checkValid(); - SwiftInstanceCleanup cleanup = instance.$createCleanup(); + SwiftInstanceCleanup cleanup = instance.$cleanup(); this.resources.add(cleanup); } diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java index 01734d75b..7c8c89344 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java @@ -54,11 +54,13 @@ public interface JNISwiftInstance extends SwiftInstance { */ long $typeMetadataAddress(); - @Override + /** + * Build a fresh {@link SwiftInstanceCleanup} for this instance. + *

+ * Concrete implementations are expected to call this once during construction + * and cache the result in a field exposed via {@link #$cleanup()}. + */ default SwiftInstanceCleanup $createCleanup() { - return new JNISwiftInstanceCleanup( - $createDestroyFunction(), - $statusDestroyedFlag() - ); + return new JNISwiftInstanceCleanup($createDestroyFunction()); } } diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstanceCleanup.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstanceCleanup.java index 1dce368c8..3719c3ad3 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstanceCleanup.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstanceCleanup.java @@ -14,20 +14,29 @@ package org.swift.swiftkit.core; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; class JNISwiftInstanceCleanup implements SwiftInstanceCleanup { + private static final AtomicIntegerFieldUpdater DESTROYED = + AtomicIntegerFieldUpdater.newUpdater(JNISwiftInstanceCleanup.class, "destroyed"); + private final Runnable destroyFunction; - private final AtomicBoolean statusDestroyedFlag; - public JNISwiftInstanceCleanup(Runnable destroyFunction, AtomicBoolean statusDestroyedFlag) { + @SuppressWarnings("unused") // accessed via DESTROYED field updater + private volatile int destroyed; + + public JNISwiftInstanceCleanup(Runnable destroyFunction) { this.destroyFunction = destroyFunction; - this.statusDestroyedFlag = statusDestroyedFlag; + } + + @Override + public boolean isDestroyed() { + return destroyed != 0; } @Override public void run() { - if (statusDestroyedFlag.compareAndSet(false, true)) { + if (DESTROYED.compareAndSet(this, 0, 1)) { destroyFunction.run(); } else { throw new IllegalStateException("Double destruction attempt detected!"); diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java index 145af3769..865a368ea 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java @@ -14,8 +14,6 @@ package org.swift.swiftkit.core; -import java.util.concurrent.atomic.AtomicBoolean; - public interface SwiftInstance { /** * Pointer to the {@code self} of the underlying Swift object or value. @@ -27,20 +25,16 @@ public interface SwiftInstance { long $memoryAddress(); /** - * Called when the arena has decided the value should be destroyed. + * Returns the cleanup associated with this instance. *

- * Warning: The cleanup action must not capture {@code this}. - */ - SwiftInstanceCleanup $createCleanup(); - - /** - * Exposes a boolean value which can be used to indicate if the object was destroyed. + * The same cleanup instance is returned on every call. The cleanup also serves as the + * destroyed-state holder, allowing callers to poll {@link SwiftInstanceCleanup#isDestroyed()} + * even after this instance has been GC-ed. *

- * This is exposing the object, rather than performing the action because we don't want to accidentally - * form a strong reference to the {@code SwiftInstance} which could prevent the cleanup from running, - * if using an GC managed instance (e.g. using an {@code AutoSwiftMemorySession}. + * Warning: The cleanup must not capture {@code this}. */ - AtomicBoolean $statusDestroyedFlag(); + SwiftInstanceCleanup $cleanup(); + /** * Ensures that this instance has not been destroyed. *

@@ -49,7 +43,7 @@ public interface SwiftInstance { * use-after-free errors. */ default void $ensureAlive() { - if (this.$statusDestroyedFlag().get()) { + if (this.$cleanup().isDestroyed()) { throw new IllegalStateException("Attempted to call method on already destroyed instance of " + getClass().getSimpleName() + "!"); } } diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstanceCleanup.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstanceCleanup.java index 564169687..54afe1387 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstanceCleanup.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstanceCleanup.java @@ -16,5 +16,13 @@ /** * A Swift memory instance cleanup, e.g. count-down a reference count and destroy a class, or destroy struct/enum etc. + *

+ * Implementations also serve as the destroyed-state holder for their associated {@link SwiftInstance}, + * exposing {@link #isDestroyed()} which can be polled even after the instance has been GC-ed. */ -public interface SwiftInstanceCleanup extends Runnable {} \ No newline at end of file +public interface SwiftInstanceCleanup extends Runnable { + /** + * Whether this cleanup has run, i.e. the associated instance has been destroyed. + */ + boolean isDestroyed(); +} diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/collections/SwiftDictionaryMap.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/collections/SwiftDictionaryMap.java index 58489557d..68f4d5c73 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/collections/SwiftDictionaryMap.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/collections/SwiftDictionaryMap.java @@ -15,7 +15,6 @@ package org.swift.swiftkit.core.collections; import java.util.*; -import java.util.concurrent.atomic.AtomicBoolean; import org.swift.swiftkit.core.*; @@ -33,10 +32,11 @@ public class SwiftDictionaryMap extends AbstractMap implements JNISwiftInstance { private final long selfPointer; - private final AtomicBoolean destroyed = new AtomicBoolean(false); + private final SwiftInstanceCleanup cleanup; private SwiftDictionaryMap(long selfPointer) { this.selfPointer = selfPointer; + this.cleanup = $createCleanup(); } public static SwiftDictionaryMap wrapMemoryAddressUnsafe(long selfPointer, SwiftArena arena) { @@ -58,8 +58,8 @@ public static SwiftDictionaryMap wrapMemoryAddressUnsafe(long selfP } @Override - public AtomicBoolean $statusDestroyedFlag() { - return destroyed; + public SwiftInstanceCleanup $cleanup() { + return cleanup; } @Override diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/collections/SwiftSet.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/collections/SwiftSet.java index 6779ba199..352c93583 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/collections/SwiftSet.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/collections/SwiftSet.java @@ -15,7 +15,6 @@ package org.swift.swiftkit.core.collections; import java.util.*; -import java.util.concurrent.atomic.AtomicBoolean; import org.swift.swiftkit.core.*; @@ -32,10 +31,11 @@ public class SwiftSet extends AbstractSet implements JNISwiftInstance { private final long selfPointer; - private final AtomicBoolean destroyed = new AtomicBoolean(false); + private final SwiftInstanceCleanup cleanup; private SwiftSet(long selfPointer) { this.selfPointer = selfPointer; + this.cleanup = $createCleanup(); } public static SwiftSet wrapMemoryAddressUnsafe(long selfPointer, SwiftArena arena) { @@ -57,8 +57,8 @@ public static SwiftSet wrapMemoryAddressUnsafe(long selfPointer, SwiftAre } @Override - public AtomicBoolean $statusDestroyedFlag() { - return destroyed; + public SwiftInstanceCleanup $cleanup() { + return cleanup; } @Override diff --git a/SwiftKitCore/src/test/java/org/swift/swiftkit/AutoArenaTest.java b/SwiftKitCore/src/test/java/org/swift/swiftkit/AutoArenaTest.java index 120934215..7dd1f3cdd 100644 --- a/SwiftKitCore/src/test/java/org/swift/swiftkit/AutoArenaTest.java +++ b/SwiftKitCore/src/test/java/org/swift/swiftkit/AutoArenaTest.java @@ -17,8 +17,7 @@ import org.junit.jupiter.api.Test; import org.swift.swiftkit.core.JNISwiftInstance; import org.swift.swiftkit.core.SwiftArena; - -import java.util.concurrent.atomic.AtomicBoolean; +import org.swift.swiftkit.core.SwiftInstanceCleanup; public class AutoArenaTest { @@ -29,7 +28,7 @@ public void cleaner_releases_native_resource() { // This object is registered to the arena. var object = new FakeSwiftInstance(arena); - var statusDestroyedFlag = object.$statusDestroyedFlag(); + var cleanup = object.$cleanup(); // Release the object and hope it gets GC-ed soon @@ -37,7 +36,7 @@ public void cleaner_releases_native_resource() { object = null; var i = 1_000; - while (!statusDestroyedFlag.get()) { + while (!cleanup.isDestroyed()) { System.runFinalization(); System.gc(); @@ -48,9 +47,10 @@ public void cleaner_releases_native_resource() { } private static class FakeSwiftInstance implements JNISwiftInstance { - AtomicBoolean $state$destroyed = new AtomicBoolean(false); + private final SwiftInstanceCleanup cleanup; public FakeSwiftInstance(SwiftArena arena) { + this.cleanup = $createCleanup(); arena.register(this); } @@ -69,8 +69,8 @@ public FakeSwiftInstance(SwiftArena arena) { } @Override - public AtomicBoolean $statusDestroyedFlag() { - return $state$destroyed; + public SwiftInstanceCleanup $cleanup() { + return cleanup; } } } diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java index 7063fefb6..f9fc8553d 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java @@ -56,7 +56,7 @@ public void register(SwiftInstance instance) { // We make sure we don't capture `instance` in the // cleanup action, so we can ignore the warning below. - var cleanupAction = instance.$createCleanup(); + var cleanupAction = instance.$cleanup(); cleaner.register(instance, cleanupAction); } diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftErrorInstance.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftErrorInstance.java index 224faaec4..4fa41f3c7 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftErrorInstance.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftErrorInstance.java @@ -18,7 +18,6 @@ import org.swift.swiftkit.core.SwiftInstanceCleanup; import java.lang.foreign.MemorySegment; -import java.util.concurrent.atomic.AtomicBoolean; /** * Base class for Swift errors passed across the FFM boundary. @@ -27,17 +26,19 @@ */ public abstract class FFMSwiftErrorInstance extends Exception implements SwiftInstance { private final MemorySegment memorySegment; - private final AtomicBoolean $state$destroyed = new AtomicBoolean(false); + private final FFMSwiftInstanceCleanup cleanup; protected FFMSwiftErrorInstance(String message, MemorySegment segment, AllocatingSwiftArena arena) { super(message); this.memorySegment = segment; + this.cleanup = new FFMSwiftInstanceCleanup(segment, $swiftType()); arena.register(this); } protected FFMSwiftErrorInstance(MemorySegment segment, AllocatingSwiftArena arena) { super(); this.memorySegment = segment; + this.cleanup = new FFMSwiftInstanceCleanup(segment, $swiftType()); arena.register(this); } @@ -50,21 +51,13 @@ protected FFMSwiftErrorInstance(MemorySegment segment, AllocatingSwiftArena aren return $memorySegment().address(); } - public final AtomicBoolean $statusDestroyedFlag() { - return $state$destroyed; + @Override + public final SwiftInstanceCleanup $cleanup() { + return this.cleanup; } /** * The Swift type metadata of this type. */ public abstract SwiftAnyType $swiftType(); - - @Override - public SwiftInstanceCleanup $createCleanup() { - return new FFMSwiftInstanceCleanup( - $memorySegment(), - $swiftType(), - $statusDestroyedFlag() - ); - } } diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java index bc8a2d9ed..11476087f 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java @@ -18,14 +18,10 @@ import org.swift.swiftkit.core.SwiftInstanceCleanup; import java.lang.foreign.MemorySegment; -import java.util.concurrent.atomic.AtomicBoolean; public abstract class FFMSwiftInstance implements SwiftInstance { private final MemorySegment memorySegment; - - // TODO: make this a flagset integer and/or use a field updater - /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */ - private final AtomicBoolean $state$destroyed = new AtomicBoolean(false); + private final FFMSwiftInstanceCleanup cleanup; /** * The designated constructor of any imported Swift types. @@ -35,6 +31,7 @@ public abstract class FFMSwiftInstance implements SwiftInstance { */ protected FFMSwiftInstance(MemorySegment segment, AllocatingSwiftArena arena) { this.memorySegment = segment; + this.cleanup = new FFMSwiftInstanceCleanup(segment, $swiftType()); // Only register once we have fully initialized the object since this will need the object pointer. arena.register(this); @@ -57,24 +54,9 @@ protected FFMSwiftInstance(MemorySegment segment, AllocatingSwiftArena arena) { */ public abstract SwiftAnyType $swiftType(); - /** - * Exposes a boolean value which can be used to indicate if the object was destroyed. - *

- * This is exposing the object, rather than performing the action because we don't want to accidentally - * form a strong reference to the {@code SwiftInstance} which could prevent the cleanup from running, - * if using an GC managed instance (e.g. using an {@code AutoSwiftMemorySession}. - */ - public final AtomicBoolean $statusDestroyedFlag() { - return this.$state$destroyed; - } - @Override - public SwiftInstanceCleanup $createCleanup() { - return new FFMSwiftInstanceCleanup( - $memorySegment(), - $swiftType(), - $statusDestroyedFlag() - ); + public final SwiftInstanceCleanup $cleanup() { + return this.cleanup; } /** diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java index 97c4808d5..6f4f6e1ee 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java @@ -19,22 +19,31 @@ import static org.swift.swiftkit.ffm.SwiftJavaLogGroup.LIFECYCLE; import java.lang.foreign.MemorySegment; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; + +class FFMSwiftInstanceCleanup implements SwiftInstanceCleanup { + private static final AtomicIntegerFieldUpdater DESTROYED = + AtomicIntegerFieldUpdater.newUpdater(FFMSwiftInstanceCleanup.class, "destroyed"); -public class FFMSwiftInstanceCleanup implements SwiftInstanceCleanup { private final MemorySegment memoryAddress; private final SwiftAnyType type; - private final AtomicBoolean statusDestroyedFlag; - public FFMSwiftInstanceCleanup(MemorySegment memoryAddress, SwiftAnyType type, AtomicBoolean statusDestroyedFlag) { + @SuppressWarnings("unused") // accessed via DESTROYED field updater + private volatile int destroyed; + + public FFMSwiftInstanceCleanup(MemorySegment memoryAddress, SwiftAnyType type) { this.memoryAddress = memoryAddress; this.type = type; - this.statusDestroyedFlag = statusDestroyedFlag; + } + + @Override + public boolean isDestroyed() { + return destroyed != 0; } @Override public void run() { - if (statusDestroyedFlag.compareAndSet(false, true)) { + if (DESTROYED.compareAndSet(this, 0, 1)) { // Allow null pointers just for AutoArena tests. if (type != null && memoryAddress != null) { SwiftRuntime.log(LIFECYCLE, "Destroy swift value [" + type.getSwiftName() + "]: " + memoryAddress); diff --git a/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java b/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java index 18c0a5af0..024696ed1 100644 --- a/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java +++ b/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java @@ -16,9 +16,7 @@ import org.junit.jupiter.api.Test; -import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; -import java.util.concurrent.atomic.AtomicBoolean; public class AutoArenaTest { @@ -29,7 +27,7 @@ public void cleaner_releases_native_resource() { // This object is registered to the arena. var object = new FakeSwiftInstance(arena); - var statusDestroyedFlag = object.$statusDestroyedFlag(); + var cleanup = object.$cleanup(); // Release the object and hope it gets GC-ed soon @@ -37,7 +35,7 @@ public void cleaner_releases_native_resource() { object = null; var i = 1_000; - while (!statusDestroyedFlag.get()) { + while (!cleanup.isDestroyed()) { System.runFinalization(); System.gc(); diff --git a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift index 00d2b4bdb..e2ac9830a 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift @@ -58,7 +58,6 @@ struct JNIClassTests { import org.swift.swiftkit.core.util.*; import org.swift.swiftkit.core.collections.*; import java.util.*; - import java.util.concurrent.atomic.AtomicBoolean; import org.swift.swiftkit.core.annotations.*; """, """ @@ -85,6 +84,7 @@ struct JNIClassTests { private MyClass(long selfPointer, SwiftArena swiftArena) { SwiftObjects.requireNonZero(selfPointer, "selfPointer"); this.selfPointer = selfPointer; + this.$cleanup = $createCleanup(); // Only register once we have fully initialized the object since this will need the object pointer. swiftArena.register(this); diff --git a/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift index 8c7a37148..5339e07d6 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift @@ -46,7 +46,6 @@ struct JNIEnumTests { import org.swift.swiftkit.core.util.*; import org.swift.swiftkit.core.collections.*; import java.util.*; - import java.util.concurrent.atomic.AtomicBoolean; import org.swift.swiftkit.core.annotations.*; """, """ @@ -65,6 +64,7 @@ struct JNIEnumTests { private MyEnum(long selfPointer, SwiftArena swiftArena) { SwiftObjects.requireNonZero(selfPointer, "selfPointer"); this.selfPointer = selfPointer; + this.$cleanup = $createCleanup(); // Only register once we have fully initialized the object since this will need the object pointer. swiftArena.register(this); diff --git a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift index b0c3bfbb7..8b63d982a 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift @@ -53,7 +53,6 @@ struct JNIModuleTests { import org.swift.swiftkit.core.util.*; import org.swift.swiftkit.core.collections.*; import java.util.*; - import java.util.concurrent.atomic.AtomicBoolean; import org.swift.swiftkit.core.annotations.*; public final class SwiftModule { diff --git a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift index 8739a96a1..c83c8af6e 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift @@ -71,6 +71,7 @@ struct JNIStructTests { private MyStruct(long selfPointer, SwiftArena swiftArena) { SwiftObjects.requireNonZero(selfPointer, "selfPointer"); this.selfPointer = selfPointer; + this.$cleanup = $createCleanup(); // Only register once we have fully initialized the object since this will need the object pointer. swiftArena.register(this);