• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * 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.internal.util.logDuration
20 
21 internal val neverImpl: EventsImpl<Nothing> = EventsImplCheap { null }
22 
23 internal class MapNode<A, B>(val upstream: PullNode<A>, val transform: EvalScope.(A, Int) -> B) :
24     PullNode<B> {
getPushEventnull25     override fun getPushEvent(logIndent: Int, evalScope: EvalScope): B =
26         logDuration(logIndent, "MapNode.getPushEvent") {
27             val upstream =
28                 logDuration("upstream event") { upstream.getPushEvent(currentLogIndent, evalScope) }
29             logDuration("transform") { evalScope.transform(upstream, currentLogIndent) }
30         }
31 }
32 
mapImplnull33 internal inline fun <A, B> mapImpl(
34     crossinline upstream: EvalScope.() -> EventsImpl<A>,
35     noinline transform: EvalScope.(A, Int) -> B,
36 ): EventsImpl<B> = EventsImplCheap { downstream ->
37     upstream().activate(evalScope = this, downstream)?.let { (connection, needsEval) ->
38         ActivationResult(
39             connection =
40                 NodeConnection(
41                     directUpstream = MapNode(connection.directUpstream, transform),
42                     schedulerUpstream = connection.schedulerUpstream,
43                 ),
44             needsEval = needsEval,
45         )
46     }
47 }
48 
49 internal class CachedNode<A>(
50     private val transactionCache: TransactionCache<Lazy<A>>,
51     val upstream: PullNode<A>,
52 ) : PullNode<A> {
getPushEventnull53     override fun getPushEvent(logIndent: Int, evalScope: EvalScope): A =
54         logDuration(logIndent, "CachedNode.getPushEvent") {
55             val deferred =
56                 logDuration("CachedNode.getOrPut", false) {
57                     transactionCache.getOrPut(evalScope) {
58                         evalScope.deferAsync {
59                             logDuration("CachedNode.getUpstreamEvent") {
60                                 upstream.getPushEvent(currentLogIndent, evalScope)
61                             }
62                         }
63                     }
64                 }
65             logDuration("await") { deferred.value }
66         }
67 }
68 
cachednull69 internal fun <A> EventsImpl<A>.cached(): EventsImpl<A> {
70     val key = TransactionCache<Lazy<A>>()
71     return EventsImplCheap { it ->
72         activate(this, it)?.let { (connection, needsEval) ->
73             ActivationResult(
74                 connection =
75                     NodeConnection(
76                         directUpstream = CachedNode(key, connection.directUpstream),
77                         schedulerUpstream = connection.schedulerUpstream,
78                     ),
79                 needsEval = needsEval,
80             )
81         }
82     }
83 }
84