Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 66a90914 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[kairos] simplify scope lifetime tracking" into main

parents ff5f4b14 ce250df3
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -167,7 +167,7 @@ internal class LocalNetwork(
    val nameData: NameData,
    private val network: Network,
    private val scope: CoroutineScope,
    private val aliveLazy: Lazy<State<Boolean>>,
    private val deathSignalLazy: Lazy<Events<Any>>,
) : KairosNetwork {

    init {
@@ -208,7 +208,13 @@ internal class LocalNetwork(
        BuildScopeImpl(
            nameData,
            epoch,
            stateScope = StateScopeImpl(nameData, epoch, evalScope = this, aliveLazy = aliveLazy),
            stateScope =
                StateScopeImpl(
                    nameData,
                    epoch,
                    evalScope = this,
                    deathSignalLazy = deathSignalLazy,
                ),
            coroutineScope = coroutineScope,
        )

@@ -276,7 +282,7 @@ internal constructor(private val network: Network, private val scope: CoroutineS
        FullNameTag(lazyOf("root"), "launchKairosNetwork"),
        network,
        scope,
        lazyOf(stateOf(true)),
        lazyOf(emptyEvents),
    )

/** Constructs a new [RootKairosNetwork] in the given [CoroutineScope] and [CoalescingPolicy]. */
+5 −8
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@ import com.android.systemui.kairos.internal.util.childScope
import com.android.systemui.kairos.internal.util.invokeOnCancel
import com.android.systemui.kairos.internal.util.launchImmediate
import com.android.systemui.kairos.launchEffect
import com.android.systemui.kairos.observeSync
import com.android.systemui.kairos.skipNext
import com.android.systemui.kairos.takeUntil
import com.android.systemui.kairos.util.Maybe
@@ -81,7 +80,7 @@ internal class BuildScopeImpl(
        get() = coroutineScope.coroutineContext.job

    override val kairosNetwork: LocalNetwork by lazy {
        LocalNetwork(nameData, network, coroutineScope, stateScope.aliveLazy)
        LocalNetwork(nameData, network, coroutineScope, stateScope.deathSignalLazy)
    }

    override fun <T> events(
@@ -312,7 +311,7 @@ internal class BuildScopeImpl(
                            asyncNameData,
                            network = this@BuildScopeImpl.network,
                            scope = this@newScope,
                            aliveLazy = childStateScope.aliveLazy,
                            deathSignalLazy = childStateScope.deathSignalLazy,
                        )
                    val scope =
                        object : KairosCoroutineScope, CoroutineScope by this@newScope {
@@ -327,7 +326,7 @@ internal class BuildScopeImpl(
                    nameData,
                    network = this@BuildScopeImpl.network,
                    scope = childScope,
                    aliveLazy = this@BuildScopeImpl.stateScope.aliveLazy,
                    deathSignalLazy = this@BuildScopeImpl.stateScope.deathSignalLazy,
                )
        }

@@ -401,9 +400,7 @@ internal class BuildScopeImpl(
                        (newCoroutineScope.coroutineContext.job as CompletableJob).complete()
                    }
                )
                observeSync(nameData + "observeLifetime", alive) {
                    if (!it) newCoroutineScope.cancel()
                }
                deathSignal.observeSync(nameData + "observeLifetime") { newCoroutineScope.cancel() }
            }
    }

@@ -437,7 +434,7 @@ private fun EvalScope.reenterBuildScope(
                outerScope.stateScope.nameData,
                outerScope.stateScope.createdEpoch,
                evalScope = this,
                aliveLazy = outerScope.stateScope.aliveLazy,
                deathSignalLazy = outerScope.stateScope.deathSignalLazy,
            ),
        coroutineScope,
    )
+1 −2
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.systemui.kairos.internal

import com.android.systemui.kairos.BuildScope
import com.android.systemui.kairos.Events
import com.android.systemui.kairos.State
import com.android.systemui.kairos.StateScope
import com.android.systemui.kairos.TransactionScope
import com.android.systemui.kairos.util.NameData
@@ -31,7 +30,7 @@ internal interface InitScope {
internal interface EvalScope : NetworkScope, DeferScope, TransactionScope

internal interface InternalStateScope : EvalScope, StateScope {
    val alive: State<Boolean>
    val deathSignal: Events<Any>

    fun <A> truncateToScope(events: Events<A>, nameData: NameData): Events<A>
}
+17 −37
Original line number Diff line number Diff line
@@ -27,16 +27,13 @@ import com.android.systemui.kairos.State
import com.android.systemui.kairos.StateInit
import com.android.systemui.kairos.StateScope
import com.android.systemui.kairos.Stateful
import com.android.systemui.kairos.changes
import com.android.systemui.kairos.emptyEvents
import com.android.systemui.kairos.groupByKey
import com.android.systemui.kairos.init
import com.android.systemui.kairos.map
import com.android.systemui.kairos.mapCheap
import com.android.systemui.kairos.mapCheapUnsafe
import com.android.systemui.kairos.mergeLeft
import com.android.systemui.kairos.skipNext
import com.android.systemui.kairos.switchEvents
import com.android.systemui.kairos.switchEventsPromptly
import com.android.systemui.kairos.util.Maybe
import com.android.systemui.kairos.util.NameData
import com.android.systemui.kairos.util.NameTag
@@ -50,14 +47,14 @@ internal class StateScopeImpl(
    val nameData: NameData,
    val createdEpoch: Long,
    val evalScope: EvalScope,
    val aliveLazy: Lazy<State<Boolean>>,
    val deathSignalLazy: Lazy<Events<Any>>,
) : InternalStateScope, EvalScope by evalScope {

    init {
        nameData.forceInit()
    }

    override val alive: State<Boolean> by aliveLazy
    override val deathSignal: Events<Any> by deathSignalLazy

    override fun <A> deferredStateScope(block: StateScope.() -> A): DeferredValue<A> =
        DeferredValue(deferAsync { block() })
@@ -69,7 +66,7 @@ internal class StateScopeImpl(
        val nameData = name.toNameData("Events.holdStateDeferred")
        // Ensure state is only collected until the end of this scope
        return truncateToScope(this@holdStateDeferred, nameData + "truncatedChanges")
            .holdStateInternalDeferred(nameData, this@StateScopeImpl, initialValue.unwrapped)
            .holdStateDeferredUnsafe(nameData, this@StateScopeImpl, initialValue.unwrapped)
    }

    override fun <K, V> Events<Map<K, Maybe<V>>>.foldStateMapIncrementally(
@@ -153,34 +150,17 @@ internal class StateScopeImpl(
            nameData,
            epoch,
            evalScope,
            aliveLazy =
            deathSignalLazy =
                lazy {
                    alive
                        .changes(nameData + "parentAliveChanges")
                        .mapCheap { now }
                        .holdStateInternalDeferred(
                            nameData + "deathSignalInner",
                            this,
                            deferAsync {
                                if (alive.sample()) {
                                    childEndSignal.nextOnlyInternal(
                                        nameData + "firstEndSignal",
                                        this,
                                    )
                                } else {
                                    now
                                }
                            },
                        )
                        .switchEventsPromptly(nameData + "deathSignal")
                        .mapCheap(nameData + "mapFalse") { false }
                        .holdStateInternal(nameData + "isAlive", this, true)
                    mergeLeft(nameData + "mergedDeathSignal", deathSignal, childEndSignal)
                        .nextOnlyUnsafe(nameData + "firstEndSignal", this)
                },
        )

    override fun <A> truncateToScope(events: Events<A>, nameData: NameData): Events<A> =
        alive
            .mapCheapUnsafe(nameData + "mapCheapSwitchOff") { if (it) events else emptyEvents }
        deathSignal
            .mapCheap(nameData + "switchOff") { emptyEvents }
            .holdStateUnsafe(nameData + "switchedIn", this, events)
            .switchEvents(nameData)

    override fun toString(): String = "${super.toString()}[$nameData]"
@@ -191,33 +171,33 @@ private fun EvalScope.reenterStateScope(outerScope: StateScopeImpl) =
        outerScope.nameData,
        outerScope.createdEpoch,
        evalScope = this,
        aliveLazy = outerScope.aliveLazy,
        deathSignalLazy = outerScope.deathSignalLazy,
    )

private fun <A> Events<A>.nextOnlyInternal(nameData: NameData, evalScope: EvalScope): Events<A> =
private fun <A> Events<A>.nextOnlyUnsafe(nameData: NameData, evalScope: EvalScope): Events<A> =
    if (this === emptyEvents) {
        this
    } else {
        EventsLoop<A>().apply {
            loopback =
                mapCheap(nameData + "shutoffEvent") { emptyEvents }
                    .holdStateInternal(nameData + "state", evalScope, this@nextOnlyInternal)
                    .holdStateUnsafe(nameData + "state", evalScope, this@nextOnlyUnsafe)
                    .switchEvents(nameData)
        }
    }

private fun <A> Events<A>.holdStateInternal(
private fun <A> Events<A>.holdStateUnsafe(
    nameData: NameData,
    evalScope: EvalScope,
    initialValue: A,
): State<A> = holdStateInternalDeferred(nameData, evalScope, lazyOf(initialValue))
): State<A> = holdStateDeferredUnsafe(nameData, evalScope, lazyOf(initialValue))

private fun <A> Events<A>.holdStateInternalDeferred(
private fun <A> Events<A>.holdStateDeferredUnsafe(
    nameData: NameData,
    evalScope: EvalScope,
    initialValue: Lazy<A>,
): State<A> {
    val changes = this@holdStateInternalDeferred
    val changes = this@holdStateDeferredUnsafe
    val impl =
        activatedStateSource(
            nameData,