I have a problem wrapping my head around coroutine...
# coroutines
b
I have a problem wrapping my head around coroutines and wrapping coroutines around an existing callback-based API: https://gist.github.com/Bombe/fb1ec487ea03614d96e9d152f21e64cc – the exception from line 55 is being thrown from line 55 and not from line 57, like I’d expect. What’s going on there?
z
"being thrown from" is kind of ambiguous. A lot of async code doesn't actually "throw" exceptions, since throwing is simply how you leave the stack frame early. Instead, exceptions are passed around explicitly. Stack traces are captured when exceptions are created (which is traditionally the same place as from where they're thrown). Your exception is created on like 55, so that's the source location that the captured stack trace is going to show.
Unrelated, but your code has a race on line 11 - instead of a separate
isCompleted
check, it would be better to check the return value of
calledFirst.complete()
- this call will return false if the deferred was already completed.
b
Thing is, the exception is not showing up in the place it’s supposed to be (in the
assertFailsWith
).
z
What do you mean by “showing up”?
b
I have in the mean time rewritten both the class and the test (please check it again). What I mean is that I can see the strings
a
,
b
, and
d
being printed but not the other ones, which must mean that await() actually does throw the exception; however, a stack trace is still printed to stderr, and the test still fails.
z
I think your test is failing because
async
actually reports exceptions twice – it will send it up the
Job
hierarchy (cancelling its parent), and throw it from
await
. If you use an orphan
Job
for the
async
coroutine, i think it will pass (e.g.
async(Job())
).
b
Yes, indeed, the test is green now… thank you for that.
I guess that’s not really preventable (because this whole structural concurrency thing), right?
What about this
supervisorScope
that’s mentioned in `async`’s kdoc? How would I use that? Is that preferable? Do I only have this problem because this is test code?
(Wrapping the
async
in a
supervisorScope
also allows the test to succeed.)
And can I somehow verify that my use of coroutine stuff in the implementation is actually kind of correct? 🙂
z
yea,
supervisorScope
is better because your async will still get cancelled if the parent scope is cancelled. There was a lot of discussion about 6 months ago about how awkward the
async
case is, but nothing seems to have come of it 😞
And can I somehow verify that my use of coroutine stuff in the implementation is actually kind of correct?
Besides the usual unit tests? I’m not aware of any formal verification static analysis tools for coroutines.
b
Okay, thank you very much. 🙂