Is there something similar to CopyableThreadContex...
# coroutines
e
Is there something similar to CopyableThreadContextElement that allows you to specify that a context should NOT BE included in child coroutines? For example if we want to make a reentrant lock:
Copy code
class Reentrant : Key<Reentrant>, Element {
  val lock = Mutex()
  override val key get() = this

  suspend fun <Return> withLock(block: suspend () -> (Return)): Return {
   if (currentCoroutineContext()[this] != null) return block()
   return lock.withLock { withContext(this) { block() } }
  }
}
Or something along these lines... we do want to make sure that:
Copy code
reentrant.withLock {
  GlobalScope.launch {
   reentrannt.withLock {}
  }
}
Is not considered recursive. I was thinking perhaps I could abuse CopyableThreadContextElement and make copyForChild return some kind of EmptyCopyableThreadContextElement. But maybe there is a better way? Seems like this might not even work because it always calls copy if the element is on the right side of newCoroutineContext
e
why would that be recursive in the first place? there is no relation between the job outside and inside the
GlobalScope.launch
e
Yes there is? They share context
For example:
Copy code
fun main() {
    runBlocking {
        println("Name: ${currentCoroutineContext()[CoroutineName]}")
        withContext(CoroutineName("test")) {
            println("Name: ${currentCoroutineContext()[CoroutineName]}")
            launch {
                println("Name: ${currentCoroutineContext()[CoroutineName]}")
            }
        }
    }
}
Result:
Copy code
Name: null
Name: CoroutineName(test)
Name: CoroutineName(test)
I need a context that doesn't make it into launch/async or any block that isn't executed sequentially.
e
yes there is with
launch
, but not with
GlobalScope.launch
as in your original example
e
Ok sure, well either way what's the solution here?
e
the solution to what?
if you're following structured concurrency, all the blocks are nested so you can simply check the context to see if a lock is already acquired
if you're not following structured concurrency, then you're not sharing context anyway
e
Copy code
reentrant.withLock {
  launch {
   reentrannt.withLock {}
  }
}
Ok but that doesn't work, so how can this be resolved?
e
https://pl.kotl.in/C_G19-jZ_ how doesn't it work?
e
Ah right, there aren't any builtins that go from currentCoroutineContext to CoroutineScope are there?
Also there isn't an unmanaged continuations library out there that you know of right?