And yet another question. Inside a `produce`, does...
# coroutines
u
And yet another question. Inside a
produce
, does `this.close()`cancel the producer? Is this documented?
v
No, it’s not. It’s not directly documented, though it’s “principle of least surprise” and all cancellations/close relations are documented
u
I thought I understand coroutines, but now I doubt 🙂 Did you see my gist trying to show an implementation of switchMap to @hannesstruss: https://gitlab.com/snippets/1725697 There are 2 funny things: 1) If I use coroutines 0.23.1 with the new global coroutineScope it breaks 2) It magically terminates on
output.close()
which is a good thing but unexpected
v
Old coroutine context is deprecated for a reason 🙂 Your code has a bug:
Copy code
source.switchMap(coroutineContext) { i ->
            produce(coroutineContext) { // <- wrong context here is inherited because switchMap lambda doesn't implement CoroutineScope
E.g.
Copy code
val switchMapped = source.switchMap(coroutineContext) { i ->
            println("Parent Job for producer: ${kotlin.coroutines.experimental.coroutineContext[Job]} vs ${coroutineContext[Job]}")
will print
StandaloneCoroutine{Active}@3941a79c vs BlockingCoroutine{Active}@27bc2616
respectively Your implementation has a bug (accidentally making parent-child relationship for all jobs) 🙂 @hannesstruss implementation looks good modulo cancellation
u
Thanks @Vsevolod Tolstopyatov [JB] for pointing this out. I still don't get it though. What's wrong with the parent/child relation? I thought this was good practice as it let's you cancel the whole tree. I guess we do agree, that the transformer jobs are always leafs in the tree. Shouldn't it be side effect free to cancel them? And should 'Done' be never printed if the transformer job is canceled?
And by the way, using coroutines 0.22.3 the code still works, even with the global coroutineContext
Well, I see, the transformer job is not a leaf node. As you pointed out, the map producer is created as a child of the transformer job. So I guess, what happens is, that the map producer (as a child) is canceled before the transformer job (parent). Now I start guessing. Does canceling the producer get the consumeEach out of suspend which will cause the cancelation for the transformer job to be postponed until next suspension?
Yes, looks like it. If I put a `yield`behind the consumeEach to give another cancelation point, things start working again. With 0.22.3 the yield was not required which seems more natural to me.
@hannesstruss ^^^