diff --git a/backend.native/tests/runtime/memory/weak1.kt b/backend.native/tests/runtime/memory/weak1.kt index 4c2c7a742bc..57dffc65550 100644 --- a/backend.native/tests/runtime/memory/weak1.kt +++ b/backend.native/tests/runtime/memory/weak1.kt @@ -10,7 +10,7 @@ import kotlin.native.ref.* class Node(var next: Node?) -@Test fun runTest() { +@Test fun runTest1() { val node1 = Node(null) val node2 = Node(node1) node1.next = node2 @@ -18,3 +18,15 @@ class Node(var next: Node?) kotlin.native.ref.WeakReference(node1) println("OK") } + +@Test fun runTest2() { + val string = "Hello" + val refString = WeakReference(string) + assertEquals(string, refString.value) + val zero = 0 + val refZero = WeakReference(zero) + assertEquals(0, refZero.value) + val long = Long.MAX_VALUE + val refLong = WeakReference(long) + assertEquals(Long.MAX_VALUE, refLong.value) +} diff --git a/runtime/src/main/cpp/Weak.cpp b/runtime/src/main/cpp/Weak.cpp index ee8c9136cfc..c99313439f7 100644 --- a/runtime/src/main/cpp/Weak.cpp +++ b/runtime/src/main/cpp/Weak.cpp @@ -49,10 +49,15 @@ extern "C" { OBJ_GETTER(makeWeakReferenceCounter, void*); OBJ_GETTER(makeObjCWeakReferenceImpl, void*); +OBJ_GETTER(makePermanentWeakReferenceImpl, ObjHeader*); // See Weak.kt for implementation details. // Retrieve link on the counter object. OBJ_GETTER(Konan_getWeakReferenceImpl, ObjHeader* referred) { + if (referred->container() == nullptr) { + RETURN_RESULT_OF(makePermanentWeakReferenceImpl, referred); + } + MetaObjHeader* meta = referred->meta_object(); #if KONAN_OBJC_INTEROP diff --git a/runtime/src/main/kotlin/kotlin/native/ref/Weak.kt b/runtime/src/main/kotlin/kotlin/native/ref/Weak.kt index 3531b011e13..81b185d1244 100644 --- a/runtime/src/main/kotlin/kotlin/native/ref/Weak.kt +++ b/runtime/src/main/kotlin/kotlin/native/ref/Weak.kt @@ -37,5 +37,11 @@ public class WeakReference { */ @Suppress("UNCHECKED_CAST") public fun get(): T? = pointer?.get() as T? + + /** + * Returns either reference to an object or null, if it was collected. + */ + public val value: T? + get() = this.get() } diff --git a/runtime/src/main/kotlin/kotlin/native/ref/WeakPrivate.kt b/runtime/src/main/kotlin/kotlin/native/ref/WeakPrivate.kt index 045ccb7fd5c..17b0a35df57 100644 --- a/runtime/src/main/kotlin/kotlin/native/ref/WeakPrivate.kt +++ b/runtime/src/main/kotlin/kotlin/native/ref/WeakPrivate.kt @@ -56,3 +56,10 @@ external internal fun getWeakReferenceImpl(referent: Any): WeakReferenceImpl @ExportForCppRuntime internal fun makeWeakReferenceCounter(referred: COpaquePointer) = WeakReferenceCounter(referred) +internal class PermanentWeakReferenceImpl(val referred: Any): kotlin.native.ref.WeakReferenceImpl() { + override fun get(): Any? = referred +} + +// Create a reference to the permanent object. +@ExportForCppRuntime +internal fun makePermanentWeakReferenceImpl(referred: Any) = PermanentWeakReferenceImpl(referred)