diff --git a/mvi/src/commonMain/kotlin/com/adidas/mvi/sideeffects/SideEffects.kt b/mvi/src/commonMain/kotlin/com/adidas/mvi/sideeffects/SideEffects.kt index 8d83727..3f936c3 100644 --- a/mvi/src/commonMain/kotlin/com/adidas/mvi/sideeffects/SideEffects.kt +++ b/mvi/src/commonMain/kotlin/com/adidas/mvi/sideeffects/SideEffects.kt @@ -9,31 +9,20 @@ import kotlinx.atomicfu.atomic * It locks itself, so you can't add and read at the same time, also it's not possible to read it at the same time from different threads, being completely thread-safe. */ -public class SideEffects() : Iterable { - private val sideEffects: AtomicRef> = atomic(ArrayList()) +public class SideEffectsprivate constructor(sideEffects: List) : Iterable { + private val sideEffects: AtomicRef> = atomic(sideEffects) - // Private constructor to initialize from an Iterable - private constructor(sideEffects: Iterable) : this() { - this.sideEffects.value.addAll(sideEffects) - } + public constructor() : this(emptyList()) public fun add(vararg sideEffectsToAdd: T): SideEffects { - val newList = sideEffects.value.toMutableList() - newList.addAll(sideEffectsToAdd) - return SideEffects(newList) + return SideEffects(sideEffects.value + sideEffectsToAdd) } public fun clear(): SideEffects { return SideEffects() } - override fun iterator(): Iterator = - iterator { - while (true) { - val currentList = sideEffects.value - if (currentList.isEmpty()) break - val nextSideEffect = currentList.removeFirstOrNull() - nextSideEffect?.let { yield(it) } - } - } + override fun iterator(): Iterator { + return sideEffects.getAndSet(emptyList()).iterator() + } } diff --git a/mvi/src/jvmTest/kotlin/com/adidas/mvi/sideeffects/SideEffectsTest.kt b/mvi/src/jvmTest/kotlin/com/adidas/mvi/sideeffects/SideEffectsTest.kt index 3b5f813..e92613f 100644 --- a/mvi/src/jvmTest/kotlin/com/adidas/mvi/sideeffects/SideEffectsTest.kt +++ b/mvi/src/jvmTest/kotlin/com/adidas/mvi/sideeffects/SideEffectsTest.kt @@ -1,16 +1,10 @@ package com.adidas.mvi.sideeffects import io.kotest.core.spec.style.BehaviorSpec -import io.kotest.matchers.booleans.shouldBeFalse import io.kotest.matchers.collections.shouldBeEmpty import io.kotest.matchers.collections.shouldContain import io.kotest.matchers.collections.shouldContainInOrder -import kotlin.time.DurationUnit import kotlin.time.ExperimentalTime -import kotlin.time.toDuration -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.sync.Semaphore @ExperimentalTime internal class SideEffectsTest : BehaviorSpec({ @@ -60,42 +54,5 @@ internal class SideEffectsTest : BehaviorSpec({ clearedSideEffects.shouldBeEmpty() } } - - `when`("I try to read SideEffects and it takes time, simulated by a semaphore") { - val firstSideEffect = TestSideEffect() - val secondSideEffectToBeAddedLater = TestSideEffect() - - var returnedSideEffects = sideEffects.add(firstSideEffect) - - val semaphore = Semaphore(2) - - val readJob = - launch(Dispatchers.Default) { - returnedSideEffects.forEach { _ -> - semaphore.acquire() // Wait for the signal - } - } - - val addJob = - launch(Dispatchers.Default) { - returnedSideEffects = sideEffects.add(secondSideEffectToBeAddedLater) - } - - semaphore.release() - - then("It should be released only by the semaphore").config( - timeout = - 5.toDuration( - DurationUnit.SECONDS, - ), - ) { - readJob.join() - addJob.join() - - readJob.isActive.shouldBeFalse() - addJob.isActive.shouldBeFalse() - returnedSideEffects.shouldContain(secondSideEffectToBeAddedLater) - } - } } })