igor.wojda
10/29/2024, 1:25 AMinternal class SynchronizedExecutor<T>() {
suspend operator fun invoke(call: suspend CoroutineScope.() -> T): T? {
// How to implement the logic ?
}
}
Usage
val synchronizedExecutor = SynchronizedExecutor()
// Can be called by multiple threads at the same time
public suspend fun getCredentials(): String {
return synchronizedExecutor {
// I want to implement a caching mechanism where multiple concurrent calls get the same result from a single execution of getCredentialsUseCase().
getCredentialsUseCase()
}
}
Sergey Dmitriev
10/29/2024, 8:11 AMinternal class SynchronizedExecutor<T> {
private var deferred: Deferred<T>? = null
suspend operator fun invoke(call: suspend CoroutineScope.() -> T): T {
val resolved = when (val current = deferred) {
null -> {
coroutineScope { async { call() } }
.also { deferred = it }
}
else -> current
}
return resolved.await()
}
}
Sam
10/29/2024, 8:11 AMSergey Dmitriev
10/29/2024, 8:12 AMDeferred
Sam
10/29/2024, 8:14 AMclass SynchronizedExecutor<T>(
call: suspend () -> T,
context: CoroutineContext = EmptyCoroutineContext
): AutoCloseable {
private val scope = CoroutineScope(context)
private val flow = call.asFlow().shareIn(scope, SharingStarted.WhileSubscribed())
suspend operator fun invoke() = flow.first()
override fun close() = scope.cancel()
}
igor.wojda
10/29/2024, 8:37 AMSam
10/29/2024, 8:37 AMSynchronizedExecutor
know whether two given functions are "the same" or not?igor.wojda
10/29/2024, 8:38 AMigor.wojda
10/29/2024, 8:38 AMSynchronizedExecutor
for each type of callDmitry Khalanskiy [JB]
10/29/2024, 10:07 AM