Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

167
Views
Custom interceptors in coroutines

I've been getting familiar with the ContinuationInterceptor section of coroutines I wrote the following section of code to verify my idea

class MyContext: CoroutineContext.Element{
    override val key : CoroutineContext.Key<*>
    get() = object : CoroutineContext.Key<MyContext>{}
}

val myInterceptor = object : ContinuationInterceptor {
    //Key is set to a non-interceptor type
    override val key : CoroutineContext.Key<MyContext>
    get() = object : CoroutineContext.Key<MyContext>{}

    override fun <T> interceptContinuation(continuation: 
        Continuation<T>): Continuation<T> {
        Log.i(TAG,"interceptor:"+continuation.context[CoroutineName].toString())
        return Continuation(EmptyCoroutineContext) {
            thread(name = "myThread") {
                continuation.resumeWith(it)
            }
        }
    }
}

lifecycleScope.launch(myInterceptor + CoroutineName("MY1")) {
    Log.i(TAG,"MY1 start:"+Thread.currentThread().name)
    fun1()

    launch(CoroutineName("MY2")) {
        Log.i(TAG,"MY2 run:"+Thread.currentThread().name)
    }
    withContext(Dispatchers.Main+CoroutineName("MY3")) {
        Log.i(TAG,"MY3 run:"+Thread.currentThread().name)
    }
    Log.i(TAG,"MY1 end:"+Thread.currentThread().name)
}

enter image description here

I don't have the myInterceptor Key specified as ContinuationInterceptor.Key.

So coroutines should not recognize it as an Interceptor.

MY1 and MY2 prove this idea, but MY3 is intercepted by myInterceptor and runs in a new thread.

I wonder:

  1. Why is myInterceptor recognized as an interceptor

  2. Why does not Dispatcher.Main work

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

The behavior of the shown code is weird. I couldn't find the exact reason why.

I fixed some obvious problems with your code, such as returning a new object from key every time, and not implementing equals. I return a singleton, so the default equals works:

class MyContext: CoroutineContext.Element {
    companion object Key : CoroutineContext.Key<MyContext>
    override val key: CoroutineContext.Key<MyContext> = Key
}

val myInterceptor = object : ContinuationInterceptor {
    override val key: CoroutineContext.Key<MyContext> = MyContext.Key

    override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> {
        println("interceptContinuation: ${continuation.context[CoroutineName]?.name}")
        return Continuation(EmptyCoroutineContext) {
            thread(name = "myThread") {
                continuation.resumeWith(it)
            }
        }
    }

    override fun toString() = "My Interceptor"
}

These fixes don't change the behavior, though, and we can see it's broken even before messing with the dispatching:

val goodCtx = CoroutineName("A") + CoroutineName("B")
val badCtx = myInterceptor + myInterceptor
println(goodCtx)
println(badCtx)

This prints

CoroutineName(B)
[My Interceptor, My Interceptor]

The first line shows you what the behavior is supposed to be, and the second one shows what it is with your implementation. You broke the equality relation. I didn't get to realizing why.

Even this finding doesn't directly explain how come your interceptor ends up being used, but it does give you some insight into what kind of things start happening when you use the framework against the intention of the authors.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!