Skip to content

Commit

Permalink
Merge pull request #2084 from InsertKoinIO/update_stately_collection_…
Browse files Browse the repository at this point in the history
…usages

Adjust collection usages
  • Loading branch information
arnaudgiuliani authored Dec 18, 2024
2 parents 849f169 + 3f126b1 commit 551dae4
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package org.koin.core

import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runTest
import org.koin.core.annotation.KoinInternalApi
import org.koin.core.component.getScopeId
import org.koin.core.context.startKoin
import org.koin.core.context.stopKoin
import org.koin.dsl.module
import org.koin.mp.KoinPlatform
import org.koin.mp.KoinPlatformTools
import org.koin.mp.Lockable
import org.koin.mp.generateId
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class ConcurrencyTest {
data class Counter(val id : String = KoinPlatformTools.generateId())
class CounterService {

private var counter = 0
private val lock = Lockable()

fun increment() = KoinPlatformTools.synchronized(lock) {
counter++
}

fun getCounter(): Int = KoinPlatformTools.synchronized(lock) { counter }
}

val jobList = 100
val jobRepeat = 100
val scopeList = 10_000

@Test
fun parallel_access() = runTest {

startKoin {
modules(module {
single { CounterService() }
})
}

try {
// Use a coroutine scope for concurrency
coroutineScope {
val jobs = List(jobList) {
launch {
repeat(jobRepeat) {
KoinPlatform.getKoin().get<CounterService>().increment()
}
}
}
jobs.joinAll()
}

assertEquals(jobList * jobRepeat, KoinPlatform.getKoin().get<CounterService>().getCounter())
} finally {
stopKoin()
}
}


@OptIn(KoinInternalApi::class)
@Test
fun parallel_create_scopes() = runTest {

startKoin {
modules(module {
scope<Counter>{
scoped { CounterService() }
}
})
}

val result = KoinPlatformTools.safeHashMap<String,Int>()

try {
coroutineScope {
val startScopes = List(scopeList) {
launch {
KoinPlatform.getKoin().apply {
val counter = Counter()
val scope = createScope<Counter>(counter.getScopeId())
scope.get<CounterService>().increment()
result[scope.id] = scope.get<CounterService>().getCounter()
scope.close()
}
}
}
startScopes.joinAll()
}
assertTrue(KoinPlatform.getKoin().instanceRegistry.instances.values.none { it.isCreated() })
} finally {
stopKoin()
}
assertEquals(scopeList, result.size)
assertTrue(result.values.all { it == 1 })
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.koin.mp

import co.touchlab.stately.collections.ConcurrentMutableMap
import co.touchlab.stately.collections.ConcurrentMutableSet
import org.koin.core.context.GlobalContext
import org.koin.core.context.KoinContext
import org.koin.core.logger.*
Expand All @@ -31,5 +32,5 @@ actual object KoinPlatformTools {
actual fun defaultContext(): KoinContext = GlobalContext
actual fun <R> synchronized(lock: Lockable, block: () -> R) = block()
actual fun <K, V> safeHashMap(): MutableMap<K, V> = ConcurrentMutableMap()
actual fun <K> safeSet(): MutableSet<K> = mutableSetOf()
actual fun <K> safeSet(): MutableSet<K> = ConcurrentMutableSet()
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.koin.mp

import co.touchlab.stately.collections.ConcurrentMutableMap
import co.touchlab.stately.collections.ConcurrentMutableSet
import co.touchlab.stately.concurrency.withLock
import org.koin.core.context.KoinContext
import org.koin.core.context.globalContextByMemoryModel
Expand All @@ -21,10 +22,8 @@ actual object KoinPlatformTools {
actual fun defaultLazyMode(): LazyThreadSafetyMode = LazyThreadSafetyMode.PUBLICATION
actual fun defaultLogger(level: Level): Logger = PrintLogger(level)
actual fun defaultContext(): KoinContext = defaultContext

actual fun <R> synchronized(lock: Lockable, block: () -> R): R = lock.lock.withLock { block() }

actual fun <R> synchronized(lock: Lockable, block: () -> R): R = lock.lock.withLock(block)
actual fun <K, V> safeHashMap(): MutableMap<K, V> = ConcurrentMutableMap()
actual fun <K> safeSet(): MutableSet<K> = mutableSetOf()
actual fun <K> safeSet(): MutableSet<K> = ConcurrentMutableSet()
}

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package org.koin.mp

import co.touchlab.stately.collections.ConcurrentMutableMap
import co.touchlab.stately.collections.ConcurrentMutableSet
import org.koin.core.context.GlobalContext
import org.koin.core.context.KoinContext
import org.koin.core.logger.*
Expand All @@ -30,6 +32,6 @@ actual object KoinPlatformTools {
actual fun defaultLogger(level: Level): Logger = PrintLogger(level)
actual fun defaultContext(): KoinContext = GlobalContext
actual fun <R> synchronized(lock: Lockable, block: () -> R) = block()
actual fun <K, V> safeHashMap(): MutableMap<K, V> = HashMap()
actual fun <K> safeSet(): MutableSet<K> = mutableSetOf()
actual fun <K, V> safeHashMap(): MutableMap<K, V> = ConcurrentMutableMap()
actual fun <K> safeSet(): MutableSet<K> = ConcurrentMutableSet()
}

0 comments on commit 551dae4

Please sign in to comment.