Simpler Coroutine Scope Creation

I’ve been migrating some code from the experimental coroutines to the release version and I find I have to add the same few lines of code to most my classes that spawn new coroutines to make them all CoroutineScoped.

It goes something like this:

class ExampleBefore : CoroutineScope { 
  private val job = Job()
  override val coroutineContext: CoroutineContext get() = job + Dispatchers.IO
}

Or another dispatcher depending on the class’ needs.

Since I’m lazy and hate duplicating this code around I made myself a new interface for this and a default implementation intended for use as a delegate implementation of the scope interface.

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlin.coroutines.CoroutineContext

interface CoroutineScopeAndJob : CoroutineScope {
  val job: Job
}

class JobBasedScope(val dispatcher: CoroutineDispatcher) : CoroutineScopeAndJob {
  override val job = Job()
  override val coroutineContext: CoroutineContext get() = job + dispatcher
}

Now in order to make a class able to spawn coroutines in it’s own tree of jobs for easier cancellation I can just delegate the interface to the implementation in a single line like this:

class ExampleAfter : CoroutineScopeAndJob by JobBasedScope(Dispatchers.IO)

Works like a charm, so I thought I’ll share it here for anyone else migrating.

Oh I also made a git gist of it all:

Question: would it make any sense to extend to be AutoClosable? Or is that redundant with what a “Coroutine Scope” is?

// from https://gist.github.com/markov/36f197a8cab2072750e99d976104670a
// class ExampleAfter : CoroutineScopeAndJob by JobBasedScope
interface CoroutineScopeAndJob : CoroutineScope, AutoCloseable {
    val job: Job
}
class JobBasedScope : CoroutineScopeAndJob {
    override val job = Job()
    override val coroutineContext: CoroutineContext get() = job + Dispatchers.Default

    override fun close() {
        job.cancel()
    }
}