diff --git a/cryptography-providers/jdk/src/jvmMain/kotlin/pooling.kt b/cryptography-providers/jdk/src/jvmMain/kotlin/pooling.kt index d9f33285..e98111d3 100644 --- a/cryptography-providers/jdk/src/jvmMain/kotlin/pooling.kt +++ b/cryptography-providers/jdk/src/jvmMain/kotlin/pooling.kt @@ -16,11 +16,9 @@ internal sealed class Pooled(protected val instantiate: () -> T) { private val pooled = ArrayDeque() override fun get(): T { - synchronized(this) { - pooled.firstOrNull() - }?.let { return it } - - return instantiate() + return synchronized(this) { + pooled.removeLastOrNull() + } ?: instantiate() } override fun put(value: T) { diff --git a/cryptography-providers/jdk/src/jvmTest/kotlin/PoolingTest.kt b/cryptography-providers/jdk/src/jvmTest/kotlin/PoolingTest.kt new file mode 100644 index 00000000..2276a9b7 --- /dev/null +++ b/cryptography-providers/jdk/src/jvmTest/kotlin/PoolingTest.kt @@ -0,0 +1,50 @@ +package dev.whyoleg.cryptography.providers.jdk + +import kotlinx.coroutines.* +import kotlinx.coroutines.test.* +import kotlin.test.* + +class PoolingTest { + + @Test + fun testSequentialUseCachedPool() { + val pool = Pooled.Cached(::Any) + val first = pool.use { it } + val second = pool.use { it } + assertSame(first, second) + val third = pool.use { it } + assertSame(second, third) + } + + @Test + fun testOverlappingUseCachedPool() { + val pool = Pooled.Cached(::Any) + val first = pool.use { it } + pool.use { i1 -> + assertSame(first, i1) + pool.use { i2 -> + assertNotSame(i1, i2) + pool.use { i3 -> + assertNotSame(i2, i3) + } + } + } + } + + @Test + fun testConcurrentUseCachedPool() = runTest { + val pool = Pooled.Cached(::Any) + val first = pool.use { it } + val instances = List(3) { + async { + pool.use { instance -> + delay(1000) + instance + } + } + }.awaitAll() + assertSame(first, instances[0]) + assertNotSame(instances[0], instances[1]) + assertNotSame(instances[1], instances[2]) + } +}