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

Marko Mitic

10/10/2019, 11:45 AM
Do coroutines have some kind of a scheduler API? (Other than launching a new coroutine with
delay()
)
e

elizarov

10/10/2019, 11:50 AM
What are you trying to achieve?
m

Marko Mitic

10/10/2019, 11:57 AM
I have some objects with time expiry, I want to execute an action whenever one of them expires
new objects can be added and existing ones can be removed (would be nice to unschedule those)
d

Dominaezzz

10/10/2019, 12:27 PM
Cancellation? Nvm
d

Dennis Schröder

10/10/2019, 12:29 PM
I wrote a simple private lib which is based on this one https://pl.kotl.in/W3yf9Y7_Z
z

Zach Klippenstein (he/him) [MOD]

10/10/2019, 12:55 PM
If you're just trying to schedule some code to run at some time in the future, launching a coroutine and calling
delay
is probably the most idiomatic way to do it with coroutines. That said, if you're on Android, WorkManager might be more appropriate depending on what kind of objects you're managing (are they only in memory or are they stored in a db?) and how far in the future you're scheduling.
l

Luis Munoz

10/10/2019, 3:00 PM
I always wondered what is the best way to schedule millions of tasks, for small tasks I will just do delay and not worry about it but I have millions of pings I have to send on 15 second intervals and right now I have 1 thread that continuously runs in a loop looking at time stamps with a delay between iterations. But not sure if this is the best way and the difference between doing that, delay or using java scheduler. If anyone knows let me know
e

elizarov

10/10/2019, 3:24 PM
The overhead for
launch { delay(time); doSomething() }
is on the order of a few hundred bytes. Do it like this if that is Ok for you. Of course, a specialized solution would be more lighter-weight, but you’ll have to write it yourself if you want it to be optimized for your particular case.
l

Luis Munoz

10/10/2019, 3:46 PM
@elizarov the problem with launch {delay()} is not the hundred bytes more the management of all those tasks, If you have millions won't it cause contention, perhaps performance problems, because when you delay you must be put back on the same thread, if that thread is busy then it can't and you will not be accurate on the delay. Underneath on the JVM I am assuming it is just an eventloop as well checking timestamps.
e

elizarov

10/10/2019, 3:53 PM
It should scale to millions without problems. You can test on your specific workloads to double check.
d

Dennis Schröder

10/10/2019, 3:58 PM
One big advantage of coroutines as a scheduler is the structured concurrency model. Think about nested scheduled tasks.
z

Zach Klippenstein (he/him) [MOD]

10/10/2019, 4:07 PM
You'd have that problem with any scheduling system - the machine can only run as many tasks at once as it has cores. And if you're using the default dispatcher, your tasks will be scheduled onto a thread pool which will scale with available cores.
n

nwh

10/11/2019, 9:17 PM
Slightly similar question - what about repeating tasks that should occur at a certain time? Obviously there are normal JVM solutions to this, like using a
ScheduledExecutorService
, just curious about kotlin solutions
d

Dennis Schröder

10/11/2019, 9:24 PM
Simple high level solution:
Copy code
suspend fun scheduledPeriodicTask(
    time: Long,
    period: Long,
    context: CoroutineContext = EmptyCoroutineContext,
    task: suspend CoroutineScope.() -> Unit
): Unit =
    withContext(context) {
        delay(time)
        while (true) {
            task()
            delay(period)
        }
    }
👍🏻 1
Copy code
launch {
  scheduledPeriodicTask(5000, 1000) {
    println("bingo")
  }
}
n

nwh

10/11/2019, 9:32 PM
Slightly off topic, but doesn't that method not inherit CoroutineScope from the outer function? I thought functions like that were supposed to be written as:
fun CoroutineScope.schedule()
so that the scope could be kept
5 Views