https://kotlinlang.org logo
#coroutines
Title
# coroutines
g

gildor

09/18/2018, 10:11 AM
I usually just pass lambda for progress. Much less overhead than channel. But you can get callback on a different thread, so should handle this case
1
l

louiscad

09/18/2018, 10:32 AM
That's a great idea, also I can take advantage of lambda default value for the cases where I don't need progress
g

gildor

09/18/2018, 10:34 AM
yes, exactly what I do. just use
null
as default value for progress
There are obvious problems with this approach: progress callback can be on any thread, callback can block progress. Channel is more robust solution, but in case of channel it is much more object created on each progress (instead of single lambda)
There is also approach to use channel that emits sealed class progress + result, but also more heavy weight solution So in many cases I ended with lambda for progress
d

Dico

09/18/2018, 10:44 AM
I like to launch coroutine with a receiver where you can set the progress. A lot like the lambda approach, but it's nicer
e

elizarov

09/18/2018, 10:45 AM
You can use suspend callback fun and if your coroutine is in the main thread, you can touch your UI right from the callback (or use
withContext
)
g

gildor

09/18/2018, 10:58 AM
problem with suspend callback that it also can suspend and slowdown you operation (same with standard lambda), but it’s fine trade off for me
d

Dico

09/18/2018, 11:01 AM
Yeah, instead of
withContext
, would probably use
launch
instead to prevent it waiting
g

gildor

09/18/2018, 11:04 AM
This creates new coroutine on each progress, sounds wasteful for me. Not so much
d

Dico

09/18/2018, 11:06 AM
Well, alternatively you could have a loop on a delay, launched on UI thread, that updates progress. It would have to be stored in a property somewhere. You probably want to make that volatile.
b

bj0

09/18/2018, 5:03 PM
coroutines are very lightweight and you shouldn't worry about creating new ones for that purpose. also one advantage of coroutines is so you don't have to use callbacks, so I would definitely prefer a channel (the 'overhead' is probably negligible compared to the callback method)
g

gildor

09/19/2018, 1:19 AM
you shouldn’t worry about creating new ones for that purpose
Yes, it just a couple of objects + work on dispatching of coroutine (that can involve context switching), but it depends on how often you notify progress, it may be that you have a lot of progress notifications and overheads of progress notifications will be visible. Overhead of channel is much higher, on each sent event you pay a few objects and atomic operations And channel is not so different for callback in this case
b

bj0

09/19/2018, 1:42 AM
I think you're falling into the trap of premature optimization. I seriously doubt for this use case you'll ever reach enough coroutines to have anything but negligible overhead. Same with channels. By using callbacks you lose some of the structural advantages gained by using coroutines/channels (see https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/).
g

gildor

09/19/2018, 1:43 AM
I see overhead of channels in my case and optimized some usages when channel is not so important for very often notifications
enough coroutines to have anything but negligible overhead
And this is not a problem of coroutines, it’s just because channels is thread and concurrently safe abstraction
Again, I don’t have anything against channel, this is abstraction that works for intended use case In some cases you can replace it with something more light weight
e

elizarov

09/19/2018, 7:05 AM
Btw, same story is in Go. Channels are great when you need them but in simple cases like progress callbacks are just as good.
d

Dico

09/19/2018, 3:06 PM
If you really want to use a channel, use a
ConflatedChannel
which will drop older elements and never suspend on
send
calls.
e

elizarov

09/19/2018, 3:13 PM
👍 Yep, for indicating progress via state update messages (list “current progress is xx%“) it works perfectly and also nicely works under load
d

Dico

09/19/2018, 3:14 PM
Yeah exactly, it's important that a more recent message makes reception of an older message obsolete. Which is usually the case with progress updates.
10 Views