dhmitchell

dhmitchell

Kotlin Coroutine Confidence: asynchronous read file

In “gallery/v14/src/main/kotlin/com/example/gallery/GetImageFromFile.kt”

  • won’t the .use always call channel.close() on exit? if so, why do you need invokeOnCancellation? or does cancellation somehow avoid the finally in the use?
  • if I wanted to iterate through the file line by line, I presume I’d call readline rather than read and otherwise it’s roughly the same?

Marked As Solved

sam-cooper

sam-cooper

Author of Kotlin Coroutine Confidence

Yes, since the use() block wraps the entire call to suspendCancellableCoroutine(), it will always close the AsynchronousFileChannel when suspendCancellableCoroutine() exits for any reason. The problem is that without that invokeOnCancellation() block, suspendCancellableCoroutine() will not exit—at least, not until we’ve finished reading the entire file.

What we’re trying to do by adding invokeOnCancellation() is to ensure that we can stop the file operation before it finishes. When the coroutine is cancelled, Kotlin executes the invokeOnCancellation() block. Calling channel.close() inside the block is how we interrupt the ongoing file operation and cause it to end early.

That means there are two different ways the file can be closed:

  1. The read() operation ends on its own, either because it reached the end of the file or because it ran into an I/O error. The suspension point resumes, and the coroutine exits the use() block, closing the channel in the process.
  2. The user cancels the coroutine before read() is done. This triggers invokeOnCancellation(), which in turn calls channel.close(). This fires the read() operation’s failed() callback, allowing the coroutine to resume from its suspended state without waiting for the rest of the data. Again, it exits the use() block, but the file channel is already closed, so that’s a no-op.

I’ll see what I can do to make all this clearer in the book! Although it’s not something you’re likely to have to deal with often, I’d like to make sure it’s clear.

As for the second question, that’s a little trickier. The AsynchronousFileChannel just deals with raw byte data, and it doesn’t have any methods for working with text or line separators. Unfortunately that means there’s no readLine() function. You could write one of your own, but you’d need to include logic to buffer the data in chunks, inspect it for line separators, and so on.

In a real application, it’s likely that the more complete feature set of the java.io libraries will outweigh any asynchronous advantage from using java.nio. If I needed to read lines from a text file, I’d probably just use a good old fashioned Reader, and accept the minor cost of a blocked IO thread. In the book, I’m not intending to advocate for using AsynchronousFileChannel all over the place—it’s just meant as a handy example of a simple (ish) operation that we can use to illustrate asynchronous callbacks. Perhaps I’ll add a quick note to that effect in the text, too.

Phew! With any luck, I’ll find a way to say all this in the book using slightly fewer words. Thanks for asking these questions—they all help me to make the explanations in the book clearer.

Where Next?

Popular Pragmatic Bookshelf topics Top

jimmykiang
This test is broken right out of the box… — FAIL: TestAgent (7.82s) agent_test.go:77: Error Trace: agent_test.go:77 agent_test.go:...
New
ianwillie
Hello Brian, I have some problems with running the code in your book. I like the style of the book very much and I have learnt a lot as...
New
mikecargal
Title: Hands-on Rust: question about get_component (page 295) (feel free to respond. “You dug you’re own hole… good luck”) I have somet...
New
HarryDeveloper
Hi @venkats, It has been mentioned in the description of ‘Supervisory Job’ title that 2 things as mentioned below result in the same eff...
New
cro
I am working on the “Your Turn” for chapter one and building out the restart button talked about on page 27. It recommends looking into ...
New
curtosis
Running mix deps.get in the sensor_hub directory fails with the following error: ** (Mix) No SSH public keys found in ~/.ssh. An ssh aut...
New
jskubick
I’m running Android Studio “Arctic Fox” 2020.3.1 Patch 2, and I’m embarrassed to admit that I only made it to page 8 before running into ...
New
mert
AWDWR 7, page 152, page 153: Hello everyone, I’m a little bit lost on the hotwire part. I didn’t fully understand it. On page 152 @rub...
New
SlowburnAZ
Getting an error when installing the dependencies at the start of this chapter: could not compile dependency :exla, "mix compile" failed...
New
dachristenson
I’ve got to the end of Ch. 11, and the app runs, with all tabs displaying what they should – at first. After switching around between St...
New

Other popular topics Top

AstonJ
What chair do you have while working… and why? Is there a ‘best’ type of chair or working position for developers?
New
DevotionGeo
I know that these benchmarks might not be the exact picture of real-world scenario, but still I expect a Rust web framework performing a ...
New
New
PragmaticBookshelf
Tailwind CSS is an exciting new CSS framework that allows you to design your site by composing simple utility classes to create complex e...
New
Exadra37
I am asking for any distro that only has the bare-bones to be able to get a shell in the server and then just install the packages as we ...
New
PragmaticBookshelf
Build highly interactive applications without ever leaving Elixir, the way the experts do. Let LiveView take care of performance, scalabi...
New
PragmaticBookshelf
Create efficient, elegant software tests in pytest, Python's most powerful testing framework. Brian Okken @brianokken Edited by Kat...
New
PragmaticBookshelf
Author Spotlight Rebecca Skinner @RebeccaSkinner Welcome to our latest author spotlight, where we sit down with Rebecca Skinner, auth...
New
DevotionGeo
I have always used antique keyboards like Cherry MX 1800 or Cherry MX 8100 and almost always have modified the switches in some way, like...
New
New

Sub Categories: