xref: /aosp_15_r20/frameworks/base/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpScope.kt (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
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
18 
19 import kotlin.coroutines.RestrictsSuspension
20 import kotlin.coroutines.resume
21 import kotlin.coroutines.resumeWithException
22 import kotlinx.coroutines.CompletableDeferred
23 import kotlinx.coroutines.Deferred
24 import kotlinx.coroutines.ExperimentalCoroutinesApi
25 import kotlinx.coroutines.suspendCancellableCoroutine
26 
27 /** Denotes [FrpScope] interfaces as [DSL markers][DslMarker]. */
28 @DslMarker annotation class FrpScopeMarker
29 
30 /**
31  * Base scope for all FRP scopes. Used to prevent implicitly capturing other scopes from in lambdas.
32  */
33 @FrpScopeMarker
34 @RestrictsSuspension
35 @ExperimentalFrpApi
36 interface FrpScope {
37     /**
38      * Returns the value held by the [FrpDeferredValue], suspending until available if necessary.
39      */
40     @ExperimentalFrpApi
41     @OptIn(ExperimentalCoroutinesApi::class)
42     suspend fun <A> FrpDeferredValue<A>.get(): A = suspendCancellableCoroutine { k ->
43         unwrapped.invokeOnCompletion { ex ->
44             ex?.let { k.resumeWithException(ex) } ?: k.resume(unwrapped.getCompleted())
45         }
46     }
47 }
48 
49 /**
50  * A value that may not be immediately (synchronously) available, but is guaranteed to be available
51  * before this transaction is completed.
52  *
53  * @see FrpScope.get
54  */
55 @ExperimentalFrpApi
56 class FrpDeferredValue<out A> internal constructor(internal val unwrapped: Deferred<A>)
57 
58 /**
59  * Returns the value held by this [FrpDeferredValue], or throws [IllegalStateException] if it is not
60  * yet available.
61  *
62  * This API is not meant for general usage within the FRP network. It is made available mainly for
63  * debugging and logging. You should always prefer [get][FrpScope.get] if possible.
64  *
65  * @see FrpScope.get
66  */
67 @ExperimentalFrpApi
68 @OptIn(ExperimentalCoroutinesApi::class)
getUnsafenull69 fun <A> FrpDeferredValue<A>.getUnsafe(): A = unwrapped.getCompleted()
70 
71 /** Returns an already-available [FrpDeferredValue] containing [value]. */
72 @ExperimentalFrpApi
73 fun <A> deferredOf(value: A): FrpDeferredValue<A> = FrpDeferredValue(CompletableDeferred(value))
74