So I'm teaching myself about coroutines and stuff ...
# coroutines
j
So I'm teaching myself about coroutines and stuff by implementing a network layer. (Yes, I know ktor has one, but I learn by making.) I'm trying to decide if, when a client opens a socket, the Job of the socket should inherit from the Job of the current context. Is that reasonable?
I also find myself writing this a lot. Is there a better way?
Copy code
launch {
    try {
        awaitCancellation()
    } finally {
        socket.close()
    }
}
Some indications are that
Job(coroutineContext.job).invokeOnCompletion
is a better option.
It's unfortunate that
Job.invokeOnCancelling
isn't a thing.
Oh, it's worse than I thought. To make that code work, I have to write this:
Copy code
launch(start = CoroutineStart.ATOMIC) {
    try {
        awaitCancellation()
    } finally {
        socket.close()
    }
}
I'll just stick with my little sub-job hack.
d
It's unfortunate that
Job.invokeOnCancelling
isn't a thing.
For these purposes,
Job.invokeOnCompletion
also shouldn't be a thing. https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html#close--
socket.close()
can throw exceptions, and `invokeOnCompletion`'s contract does not allow that.
invokeOnCompletion
is a low-level function mostly useful for writing concurrent data structures. In isolation, your solution seems perfectly fine to me. It's slightly suspicious that it looks like several coroutines are going to interact with one socket (another option to consider could be to launch a single coroutine and interact with it via a channel, for example), but I can imagine cases where what you're doing is the best approach.
j
Yeah, I'm investigating options here. I think there's only going to be one in the end.