commonMain.EventProcessor.kt Maven / Gradle / Ivy
package kt.mobius
import kt.mobius.functions.Consumer
import kotlin.js.JsName
/**
* Processes events and emits effects and models as a result of that.
*
* @param [M] model type
* @param [E] event type
* @param [F] effect descriptor type
*/
class EventProcessor internal constructor(
val store: MobiusStore,
val effectConsumer: Consumer,
val modelConsumer: Consumer
) {
private object LOCK
// concurrency note: the two below fields are only read and written in synchronized sections,
// hence no need for further coordination.
private val eventsReceivedBeforeInit = ArrayList()
private var initialised = false
fun init(): Unit = mpp.synchronized(LOCK) {
if (initialised) {
throw IllegalStateException("already initialised")
}
val first = store.init()
dispatchModel(first.model())
dispatchEffects(first.effects())
initialised = true
for (event in eventsReceivedBeforeInit) {
update(event)
}
}
fun update(event: E): Unit = mpp.synchronized(LOCK) {
if (!initialised) {
eventsReceivedBeforeInit.add(event)
return
}
val next = store.update(event)
next.ifHasModel(
object : Consumer {
override fun accept(value: M) {
dispatchModel(value)
}
})
dispatchEffects(next.effects())
}
private fun dispatchModel(model: M) {
modelConsumer.accept(model)
}
private fun dispatchEffects(effects: Iterable) {
for (effect in effects) {
effectConsumer.accept(effect)
}
}
/**
* Factory for event processors.
*
* @param [M] model type
* @param [E] event type
* @param [F] effect descriptor type
*/
data class Factory(val store: MobiusStore) {
@JsName("create")
fun create(effectConsumer: Consumer, modelConsumer: Consumer): EventProcessor {
return EventProcessor(store, effectConsumer, modelConsumer)
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy