xref: /aosp_15_r20/frameworks/base/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Output.kt (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.kairos.internal
18 
19 import com.android.systemui.kairos.util.Just
20 import kotlin.coroutines.CoroutineContext
21 import kotlin.coroutines.EmptyCoroutineContext
22 
23 internal class Output<A>(
24     val context: CoroutineContext = EmptyCoroutineContext,
<lambda>null25     val onDeath: suspend () -> Unit = {},
26     val onEmit: suspend EvalScope.(A) -> Unit,
27 ) {
28 
29     val schedulable = Schedulable.O(this)
30 
31     @Volatile var upstream: NodeConnection<A>? = null
32     @Volatile var result: Any? = NoResult
33 
34     private object NoResult
35 
36     // invoked by network
visitnull37     suspend fun visit(evalScope: EvalScope) {
38         val upstreamResult = result
39         check(upstreamResult !== NoResult) { "output visited with null upstream result" }
40         result = null
41         @Suppress("UNCHECKED_CAST") evalScope.onEmit(upstreamResult as A)
42     }
43 
killnull44     suspend fun kill() {
45         onDeath()
46     }
47 
schedulenull48     suspend fun schedule(evalScope: EvalScope) {
49         val upstreamResult =
50             checkNotNull(upstream) { "output scheduled with null upstream" }.getPushEvent(evalScope)
51         if (upstreamResult is Just) {
52             result = upstreamResult.value
53             evalScope.scheduleOutput(this)
54         }
55     }
56 }
57 
OneShotnull58 internal inline fun OneShot(crossinline onEmit: suspend EvalScope.() -> Unit): Output<Unit> =
59     Output<Unit>(onEmit = { onEmit() }).apply { result = Unit }
60