From eb9a64e5a03e0c53e1e7aa17fa818bf473bc32f8 Mon Sep 17 00:00:00 2001 From: Him188 Date: Wed, 18 Dec 2019 12:49:51 +0800 Subject: [PATCH] Add WeakRef --- .../kotlin/net/mamoe/mirai/utils/WeakRef.kt | 5 ++ .../kotlin/net.mamoe.mirai/utils/WeakRef.kt | 59 +++++++++++++++++++ .../kotlin/net/mamoe/mirai/utils/WeakRef.kt | 5 ++ 3 files changed, 69 insertions(+) create mode 100644 mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/WeakRef.kt create mode 100644 mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/WeakRef.kt create mode 100644 mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/WeakRef.kt diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/WeakRef.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/WeakRef.kt new file mode 100644 index 000000000..40035fde1 --- /dev/null +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/WeakRef.kt @@ -0,0 +1,5 @@ +package net.mamoe.mirai.utils + +import java.lang.ref.WeakReference + +actual typealias WeakRef = WeakReference \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/WeakRef.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/WeakRef.kt new file mode 100644 index 000000000..b1512930c --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/WeakRef.kt @@ -0,0 +1,59 @@ +@file:Suppress("unused") + +package net.mamoe.mirai.utils + +import kotlin.reflect.KProperty + +/** + * WeakRef that `getValue` for delegation throws an [IllegalStateException] if the referent is released by GC. Therefore it returns notnull value only + */ +inline class UnsafeWeakRef(private val weakRef: WeakRef) { + fun get(): T = weakRef.get() ?: error("WeakRef is released") + fun clear() = weakRef.clear() + + operator fun getValue(thisRef: Any?, property: KProperty<*>): T? = this.get() +} + +/** + * Weak Reference. + * In JVM, this is implemented as a typealias to `WeakReference` from JDK. + * + * Reference details: + * In JVM, instances of objects are stored in the Heap and are accessed via references. + * GC can automatically collect and release the memory used by objects that are not directly referred by any other. + * WeakReference is not direct reference, therefore it does no influence on garbage collection. + * Using weak reference can help GC with that. + * + * @see weakRef provides a WeakRef + * @see unsafeWeakRef provides a UnsafeWeakRef + */ +expect class WeakRef(referent: T) { + fun get(): T? + fun clear() +} + +/** + * Provides a weak reference to [this] + * The `getValue` for delegation returns [this] when [this] is not released by GC + */ +fun T.weakRef(): WeakRef = WeakRef(this) + +/** + * Provides a weak reference to [this]. + * The `getValue` for delegation throws an [IllegalStateException] if the referent is released by GC. Therefore it returns notnull value only + */ +fun T.unsafeWeakRef(): UnsafeWeakRef = UnsafeWeakRef(this.weakRef()) + +/** + * Provides delegate value. + * + * ```kotlin + * val bot: Bot? by param.weakRef() + * ``` + */ +operator fun WeakRef.getValue(thisRef: Any?, property: KProperty<*>): T? = this.get() + +/** + * Call the block if the referent is absent + */ +inline fun WeakRef.ifAbsent(block: (T) -> R): R? = this.get()?.let(block) \ No newline at end of file diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/WeakRef.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/WeakRef.kt new file mode 100644 index 000000000..40035fde1 --- /dev/null +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/WeakRef.kt @@ -0,0 +1,5 @@ +package net.mamoe.mirai.utils + +import java.lang.ref.WeakReference + +actual typealias WeakRef = WeakReference \ No newline at end of file