1515 */
1616package org.jitsi.utils.logging2
1717
18+ import java.lang.ref.Cleaner
1819import java.lang.ref.WeakReference
1920
2021/* *
@@ -48,22 +49,30 @@ class LogContext private constructor(
4849 var formattedContext: String = formatContext(ancestorsContext + context)
4950 private set
5051
51- /* * Child [LogContext]s of this [LogContext] (which will be notified anytime this context changes) */
52- private val childContexts: MutableList <WeakReference <LogContext >> = ArrayList ()
53-
5452 @Synchronized
5553 private fun updateFormattedContext () {
5654 val combined = ancestorsContext + context
5755 formattedContext = formatContext(combined)
5856 updateChildren(combined)
5957 }
6058
59+ /* * Child [LogContext]s of this [LogContext] (which will be notified anytime this context changes) */
60+ private val childContexts = mutableMapOf<Long , WeakReference <LogContext >>()
61+
62+ private var nextKey = 0L
63+
6164 @Synchronized
6265 fun createSubContext (childContextData : Map <String , String >) = LogContext (
6366 ancestorsContext + context,
6467 childContextData
6568 ).also {
66- childContexts.add(WeakReference (it))
69+ val key = nextKey++
70+ childContexts[key] = WeakReference (it)
71+ CLEANER .register(it) {
72+ synchronized(this @LogContext) {
73+ childContexts.remove(key)
74+ }
75+ }
6776 }
6877
6978 fun addContext (key : String , value : String ) = addContext(mapOf (key to value))
@@ -82,9 +91,8 @@ class LogContext private constructor(
8291
8392 /* * Notify children of changes in this context */
8493 @Synchronized
85- private fun updateChildren (newAncestorContext : Map <String , String >) = childContexts.apply {
86- removeIf { it.get() == null }
87- forEach { it.get()?.ancestorsContext = newAncestorContext }
94+ private fun updateChildren (newAncestorContext : Map <String , String >) = childContexts.values.forEach {
95+ it.get()?.ancestorsContext = newAncestorContext
8896 }
8997
9098 override fun toString () = formattedContext
@@ -93,6 +101,8 @@ class LogContext private constructor(
93101 const val CONTEXT_START_TOKEN = " ["
94102 const val CONTEXT_END_TOKEN = " ]"
95103
104+ private val CLEANER = Cleaner .create()
105+
96106 private fun formatContext (context : Map <String , String >): String {
97107 val s = context.entries.joinToString(separator = " " ) { " ${it.key} =${it.value} " }
98108 return if (s.isEmpty()) " " else " $CONTEXT_START_TOKEN$s$CONTEXT_END_TOKEN "
0 commit comments