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) getUnsafenull69fun <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