Mark
02/26/2024, 5:33 AMjdk.internal.misc.Unsafe.getReferenceVolatile
when calling trySend
on a BufferedChannel
(actually I’m using SingleShotEventBus). Is this something that can be mitigated?martypitt
02/27/2024, 5:28 PMPrateek Kumar
02/27/2024, 6:01 PMviewModelScope.launch(coroutineExceptionHandler) {
supervisorScope {
for (i in 0..10) {
launch {
delay(i * 1000L)
throw RuntimeException("abc")
}
}
}
}
Here in Exception Handler all 10 exceptions are recorded.
Approach 2:-
viewModelScope.launch(coroutineExceptionHandler+ SupervisorJob()) {
for (i in 0..10) {
launch {
delay(i * 1000L)
throw RuntimeException("def")
}
}
}
With this only one exception is recorded and rest are cancelled after first exception.
Why is 1 and 2 works differently? Shouldn’t the parent Job used to create child jobs?Zoltan Demant
02/28/2024, 9:18 AMimplementation(libs.coroutines.swing)
for my jvm/desktop target, but at runtime I run into issues relating to Module with the Main dispatcher had failed to initialize
and it also mentions Caused by: java.lang.NoClassDefFoundError: android/os/Looper
which seems odd given that its a desktop application. Any hints or ideas as to what might be wrong? Ive read about proguard for desktop potentially removing the dispatcher, but disabling proguard also does not seem to make a difference.ursus
02/28/2024, 7:18 PMfun <T : Any> Flow<T?>.validate( validator: (T) -> Status): Flow<Status> =
distinctUntilChanged()
.transformLatest {
val valueAndMetadata = it ?: return@transformLatest <--------------
emit(Pending)
delay(500)
val status = withContext(Dispatchers.Default) { <------------
validator(valueAndMetadata)
}
emit(status)
}
can anyone double check this?
is the usage of withContext
in a transformLatest
operator to offload a synchronous calculation correct?
I faintly remember someone complaining about switching dispatchers manually in flow operatorsPHondogo
02/29/2024, 4:43 PM@Test
fun test() {
runBlocking(Dispatchers.Default) {
try {
coroutineScope {
throw RuntimeException("test")
}
} catch (e: Exception) {
e.printStackTrace() // why cause is not null and is the same as e?
}
}
}
Sam
03/01/2024, 10:22 AMCoroutineScope(…)
requires a coroutineContext
argument. By default it creates its own Job()
. It will also use Dispatchers.Default
if I don't specify a dispatcher. So what other coroutine context would I actually want to pass? It feels strange to have to write CoroutineScope(EmptyCoroutineContext)
, not to mention misleading since the resulting scope will not have an empty coroutine context. And it's inconsistent with MainScope()
, which takes no arguments at all. 🤔Abhi
03/02/2024, 1:51 PMfun main() = runBlocking<Unit> {
launch {
launch {
launch {
delay(1000)
}
delay(1000)
}
delay(1000)
}
}
Edoardo Luppi
03/04/2024, 11:03 AMLaxystem
03/05/2024, 7:35 AMsynchronized
but afaik it doesn't really work?rkeazor
03/05/2024, 3:44 PMŁukasz Tokarski
03/06/2024, 11:46 AMManas Marthi
03/06/2024, 10:09 PMKotlinLeaner
03/06/2024, 10:55 PMstefano
03/08/2024, 10:11 AMsuspend fun
with something like GlobalContext.getContext().awaitSingle().informationINeed
. But I cannot write that code as-is in the method where it needs to run since the method is an override and doesn't have the suspend
modifier. I was considering wrapping the code with `runBlocking`; is this the way to go or am I missing something?Djuro
03/08/2024, 10:16 AMsuspend
functions?
I know that try/catch
and runCatching
swallow the CancellationException
.
Do you recommend wrapping the exception within coroutineScope
which rethrows the exceptions at the call site like this
runCatching {
coroutineScope {/*code*/}
}.OnFailure {
// handle
}
I also use runSuspendCatching
in some projects, what do you think about that approach?dave08
03/10/2024, 11:39 AMsuspend
and non suspend versions of an api (based on Lettuce Redis client's blocking and non blocking api), and I'd rather manage all the code in either one and adapt to the other, is there a major advantage to just keep them separate -- or is it better to manage the suspend version and use runBlocking as a bridge, or maybe just manage the blocking version and use with(<http://Dispatchers.IO|Dispatchers.IO>)
to make it into the suspend version?Eduard Boloș
03/11/2024, 9:29 AMcombine
of 17 (it's our main screen, if that justifies the high number 😅) Flows, only one of them is a cold flow, one is a SharedFlow
with replay = 1
, and the rest are `StateFlow`s. This `combine`'s result we turn into a StateFlow
using the stateIn
operator, and then we call collectAsStateWithLifecycle()
on it in Compose. Here I created a gist to illustrate better what I mean.
We managed to reproduce the issue on an old Moto C running Android 7, but only when we restart the Activity (that's our MVP hacky way to switch accounts 😄). However, the users that reported this issue didn't have access to the account switching feature yet, so for them it happened when simply just opening the app. Either way, the only thing we managed to figure out is that the initial state from stateIn
gets emitted and collected in Compose, and only like 4 of the 17 flows emit something (we can see that if we add .onEach { println(it) }
on all flows that are part of the big combine
). But the other flows, which are all `StateFlow`s, are not emitting their initial values 😐 We are currently stuck here, we don't know how can we even debug further.
Did anyone else encounter something similar before? Or how would you debug this issue to find the root cause? Any leads are greatly appreciated 🙏Dmitry Khalanskiy [JB]
03/11/2024, 5:28 PMNullPointerException
that occurs on some Android devices when setting the StateFlow
value (https://github.com/Kotlin/kotlinx.coroutines/issues/3820).janvladimirmostert
03/11/2024, 10:31 PMval state = MutableStateFlow<Int>(1)
launch(Dispatchers.Default) {
var counter = 1
while (true) {
state.emit(counter++)
delay(1000)
}
}
launch(Dispatchers.Default) {
while (state.value < 1000) {
print(state.value)
delay(250)
}
}
Currently this is printing
111122223333444...
but I want it to print
1234...
Use-case: I have a state inside a driver that runs across a socket that I'm building; before the next action is executed, it needs to wait until the state the socket writes back is IDLE, but if the state is already IDLE, it shouldn't have to wait for a state change.
Similarly with MutableSharedFlow with a buffer of 1, it does not suspend when using first() and keeps on printing 1111222... and using last() just never finishes since values are still being emitted:
val state = MutableSharedFlow<Int>(
replay = 1,
onBufferOverflow = BufferOverflow.DROP_OLDEST
)
launch(Dispatchers.Default) {
while (state.first() < 1000) {
println(state.first())
delay(250)
}
}
The one thing I'm sure of is that it needs to be a hot flow, the coroutine that's listening for incoming messages from the socket needs to change the state constantly whether there's a listener for the state or not. Anything that's listening on the state is only interested in the current state and if it's not the right state, it should wait for the state to switch to the right state before completing.
It feels like I'm overlooking something simple here ...Mark
03/13/2024, 4:38 AMCaused by java.lang.NoSuchMethodError: No interface method H(LR6/j;Ljava/lang/Throwable;)V in class Lkotlinx/coroutines/CoroutineExceptionHandler; or its super classes (declaration of 'kotlinx.coroutines.CoroutineExceptionHandler' appears in /data/app/~~Z-fAOaBS5ZLKRSyO1AxrHQ==/androidx.test.tools.crawler-a5LrOqdluFlu95bOrqipNw==/base.apk)
at kotlinx.coroutines.internal.CoroutineExceptionHandlerImpl_commonKt.handleUncaughtCoroutineException(CoroutineExceptionHandlerImpl_common.kt:34)
at kotlinx.coroutines.CoroutineExceptionHandlerKt.handleCoroutineException(CoroutineExceptionHandler.kt:24)
at kotlinx.coroutines.StandaloneCoroutine.handleJobException(Builders.common.kt:190)
at kotlinx.coroutines.JobSupport.finalizeFinishingState(JobSupport.kt:228)
at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:907)
at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:864)
at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:829)
at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:97)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:102)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.java:585)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:802)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:706)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:693)
Note - there was no issue with a release I made yesterday, and it’s very unlikely the few changes I made since then are related to this.Laxystem
03/13/2024, 10:40 AMawaitAll
- but when encountering a CancellationException
, it just silently ignores it instead of cancelling all the other coroutines, similarly to SupervisorJob
.kevin.cianfarini
03/13/2024, 10:55 PMFlow#flatMapLatest
seem to be frequently needed by codebases. This API in particular was last touched 5 years ago. Is there any idea when certain APIs like this will stabilize?vide
03/14/2024, 9:29 AMLukasz Kalnik
03/14/2024, 9:42 AMrunTest
automatically advance until idle instead of pausing and letting the test advance the coroutine?Lukasz Kalnik
03/15/2024, 6:46 PMwhile
loop have to check cooperatively for cancellation (e.g. using while (isActive)
), whereas "linear" (i.e. non-loop) code doesn't? 🧵Laxystem
03/17/2024, 2:02 PMmbonnin
03/18/2024, 12:30 PMchannelFlow{}
that does not dispatch until after its block
is started? Reason is I would like the caller to be able to control the buffer size while still being able to synchronously monitor collections (code in 🧵 )Jeff Lockhart
03/18/2024, 7:00 PMcoroutineContext[CoroutineDispatcher]
without requiring @OptIn(ExperimentalStdlibApi::class)
? CC: @BlakeSam
03/19/2024, 9:17 AMDispatchers.Main
quite unintuitive 😞. In a simple Swing app, the main (initial) thread and the UI thread are two different things. I'm trying to write an article talking about the two, and I literally can't find a nice way to explain it.
suspend fun main() {
println(Thread.currentThread()) // "Thread[main,…]" <- obviously the main thread, it says so in the name
withContext(Dispatchers.Main) {
println(Thread.currentThread()) // "Thread[AWT-EventQueue-0,…]" <- UI thread
}
}
Anybody got any suggestions for an intuitive way to explain it to newcomers? So far I'm stuck at "Dispatchers.Main runs code on the UI thread, which is not the same as the main thread, but it's called that because on Android it runs code on the main thread, which is usually (but not always) the same as the UI thread" 🤦😂 😭