Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promote CoroutineStart.UNDISPATCHED to non experimental API #1393

Closed
LouisCAD opened this issue Jul 29, 2019 · 6 comments
Closed

Promote CoroutineStart.UNDISPATCHED to non experimental API #1393

LouisCAD opened this issue Jul 29, 2019 · 6 comments

Comments

@LouisCAD
Copy link
Contributor

I use it quite often in places where I know it's safe to use, with the following import alias:

import kotlinx.coroutines.CoroutineStart.UNDISPATCHED as Undispatched

It'd be great to not have to have to add @UseExperimental(ExperimentalCoroutinesApi::class) to each usage.

I'm interested to know of any considerations that could justify leaving it experimental, postponing that decision or replacing it with something else (like a startDispatched: Boolean = true parameter).

@elizarov
Copy link
Contributor

elizarov commented Aug 5, 2019

As a work-around you can write in your project just once:

@UseExperimental(ExperimentalCoroutinesApi::class)
val Undispatched = kotlinx.coroutines.CoroutineStart.UNDISPATCHED 

And then you will not have to add @UseExperimental at each use-site.

@LouisCAD
Copy link
Contributor Author

LouisCAD commented Aug 5, 2019

That's a great workaround. I'll add const.

@elizarov
Copy link
Contributor

elizarov commented Aug 5, 2019

You cannot add const, though.

@LouisCAD
Copy link
Contributor Author

LouisCAD commented Aug 5, 2019

Oh, that's right, it's not a primitive but an enum entry. I can make it inline instead.

@adamp
Copy link

adamp commented Jan 26, 2021

We run into cases where we often want to initiate a concurrent process from a non-suspending context and ensure that we've run to a first suspension point to await incoming work. In compose this most recently has come up when we need to start a Recomposer before synchronously creating new compositions bound to it; if we can start the recomposition loop undispatched, we know we have not failed to observe any snapshot state invalidations that happened in between initial composition and the recomposition loop and associated snapshot observation beginning. Missing this window due to dispatch can mean we perform some initial composition work twice.

The shape of the use case reduces to something analogous to:

val channel = Channel<Data>()
coroutineScope.launch(start = CoroutineStart.UNDISPATCHED) {
    for (item in channel) {
        performWork(item)
    }
}
channel.offer(dataItem) // should return true and submit dataItem to the already-receiving job

@qwwdfsad
Copy link
Member

qwwdfsad commented Jan 29, 2021

Note:

We've discussed internally and decided that the difference between Dispatchers.Unconfined and CoroutineStart.UNDISPATCHED (the latter does not form an event loop) is expected and advanced users (that know when they need UNDISPATCHED) know the difference and won't be surprised.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants