From de635419fcde31d475200ea8238060993659ed01 Mon Sep 17 00:00:00 2001 From: Didier Garcia Date: Tue, 7 Mar 2023 00:15:01 -0500 Subject: [PATCH] Use a CopyOnWriteArrayList in Mediator instead of synchronize {}. --- .../kotlin/core/platform/Mediator.kt | 20 +++++++++++-------- .../kotlin/core/platform/Timeline.kt | 11 +++++----- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/com/segment/analytics/kotlin/core/platform/Mediator.kt b/core/src/main/java/com/segment/analytics/kotlin/core/platform/Mediator.kt index 8cd9e9a1..01f5b9a9 100644 --- a/core/src/main/java/com/segment/analytics/kotlin/core/platform/Mediator.kt +++ b/core/src/main/java/com/segment/analytics/kotlin/core/platform/Mediator.kt @@ -4,21 +4,25 @@ import com.segment.analytics.kotlin.core.Analytics import com.segment.analytics.kotlin.core.BaseEvent import com.segment.analytics.kotlin.core.platform.plugins.logger.LogFilterKind import com.segment.analytics.kotlin.core.platform.plugins.logger.segmentLog +import java.util.concurrent.CopyOnWriteArrayList import kotlin.reflect.KClass // Platform abstraction for managing plugins' execution (of a specific type) -// All operations are thread safe via the `synchronized` function -internal class Mediator(internal val plugins: MutableList) { +// All operations are thread safe via the CopyOnWriteArrayList. Which allows multiple +// threads to read the list but when a modification is made the modifier is given a new copy of +// list and that becomes the new version of the list. +// More info: https://developer.android.com/reference/kotlin/java/util/concurrent/CopyOnWriteArrayList +internal class Mediator(internal val plugins: CopyOnWriteArrayList) { - fun add(plugin: Plugin) = synchronized(plugins) { + fun add(plugin: Plugin) { plugins.add(plugin) } - fun remove(plugin: Plugin) = synchronized(plugins) { + fun remove(plugin: Plugin) { plugins.removeAll { it === plugin } // remove only if reference is the same } - fun execute(event: BaseEvent): BaseEvent? = synchronized(plugins) { + fun execute(event: BaseEvent): BaseEvent? { var result: BaseEvent? = event plugins.forEach { plugin -> @@ -42,13 +46,13 @@ internal class Mediator(internal val plugins: MutableList) { return result } - fun applyClosure(closure: (Plugin) -> Unit) = synchronized(plugins) { + fun applyClosure(closure: (Plugin) -> Unit) { plugins.forEach { closure(it) } } - fun find(pluginClass: KClass): T? = synchronized(plugins) { + fun find(pluginClass: KClass): T? { plugins.forEach { if (pluginClass.isInstance(it)) { return it as T @@ -57,7 +61,7 @@ internal class Mediator(internal val plugins: MutableList) { return null } - fun findAll(pluginClass: KClass): List = synchronized(plugins) { + fun findAll(pluginClass: KClass): List { return plugins.filter { pluginClass.isInstance(it) } as List } } diff --git a/core/src/main/java/com/segment/analytics/kotlin/core/platform/Timeline.kt b/core/src/main/java/com/segment/analytics/kotlin/core/platform/Timeline.kt index 8c5887c0..112dbd33 100644 --- a/core/src/main/java/com/segment/analytics/kotlin/core/platform/Timeline.kt +++ b/core/src/main/java/com/segment/analytics/kotlin/core/platform/Timeline.kt @@ -4,6 +4,7 @@ import com.segment.analytics.kotlin.core.Analytics import com.segment.analytics.kotlin.core.BaseEvent import com.segment.analytics.kotlin.core.System import kotlinx.coroutines.launch +import java.util.concurrent.CopyOnWriteArrayList import kotlin.reflect.KClass // Platform abstraction for managing all plugins and their execution @@ -11,11 +12,11 @@ import kotlin.reflect.KClass // Before -> Enrichment -> Destination -> After internal class Timeline { internal val plugins: Map = mapOf( - Plugin.Type.Before to Mediator(mutableListOf()), - Plugin.Type.Enrichment to Mediator(mutableListOf()), - Plugin.Type.Destination to Mediator(mutableListOf()), - Plugin.Type.After to Mediator(mutableListOf()), - Plugin.Type.Utility to Mediator(mutableListOf()) + Plugin.Type.Before to Mediator(CopyOnWriteArrayList()), + Plugin.Type.Enrichment to Mediator(CopyOnWriteArrayList()), + Plugin.Type.Destination to Mediator(CopyOnWriteArrayList()), + Plugin.Type.After to Mediator(CopyOnWriteArrayList()), + Plugin.Type.Utility to Mediator(CopyOnWriteArrayList()) ) lateinit var analytics: Analytics