Skip to content
This repository has been archived by the owner on Aug 10, 2024. It is now read-only.

Commit

Permalink
add more soft and weak references to reduce chance of memory leaks
Browse files Browse the repository at this point in the history
  • Loading branch information
sanity committed May 26, 2023
1 parent 191eedf commit a3657a9
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 6 deletions.
2 changes: 1 addition & 1 deletion api/kweb-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -1850,7 +1850,7 @@ public class kweb/state/KVal : java/lang/AutoCloseable {
public final fun close (Lkweb/state/CloseReason;)V
protected final fun finalize ()V
protected final fun getCloseReason ()Lkweb/state/CloseReason;
protected final fun getListeners ()Ljava/util/concurrent/ConcurrentHashMap;
protected final fun getListeners ()Lcom/google/common/cache/Cache;
public fun getValue ()Ljava/lang/Object;
public final fun map (Lkotlin/jvm/functions/Function1;)Lkweb/state/KVal;
public final fun onClose (Lkotlin/jvm/functions/Function0;)V
Expand Down
14 changes: 10 additions & 4 deletions src/main/kotlin/kweb/state/KVal.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package kweb.state

import com.google.common.cache.Cache
import com.google.common.cache.CacheBuilder
import kweb.util.random
import mu.two.KotlinLogging
import java.util.concurrent.ConcurrentHashMap
Expand All @@ -18,7 +20,11 @@ open class KVal<T : Any?>(value: T) : AutoCloseable{

internal val isClosed get() = closeReason != null

protected val listeners = ConcurrentHashMap<Long, (T, T) -> Unit>()
protected val listeners : Cache<Long, (T, T) -> Unit> = CacheBuilder.newBuilder()
// A listener shouldn't cause data to be retained that wouldn't otherwise be
// retained
.softValues()
.build()
private val closeHandlers = ConcurrentLinkedDeque<() -> Unit>()

/**
Expand All @@ -27,7 +33,7 @@ open class KVal<T : Any?>(value: T) : AutoCloseable{
fun addListener(listener: (T, T) -> Unit): Long {
verifyNotClosed("add a listener")
val handle = random.nextLong()
listeners[handle] = listener
listeners.put(handle, listener)
return handle
}

Expand All @@ -50,7 +56,7 @@ open class KVal<T : Any?>(value: T) : AutoCloseable{
* changes.
*/
fun removeListener(handle: Long) {
listeners.remove(handle)
listeners.invalidate(handle)
}

/**
Expand All @@ -70,7 +76,7 @@ open class KVal<T : Any?>(value: T) : AutoCloseable{
logger.debug("Updating mapped $value to $new")
val mappedValue = mapper(new)
mappedKVal.pValue = mappedValue
mappedKVal.listeners.values.forEach { listener ->
mappedKVal.listeners.asMap().values.forEach { listener ->
try {
val mappedOld = mapper(old)
if (mappedOld != mappedValue) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/kweb/state/KVar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class KVar<T : Any?>(initialValue: T) : KVal<T>(initialValue) {
override var value: T by Delegates.observable(initialValue) { _, old, new ->
if (old != new) {
verifyNotClosed("modify KVar.value")
listeners.values.forEach { listener ->
listeners.asMap().values.forEach { listener ->
try {
listener(old, new)
} catch (e: Exception) {
Expand Down

0 comments on commit a3657a9

Please sign in to comment.