85_async
You mentioned Uring, Kqueue and Dispatch. But not Evented which is just a switch to choose one of those three based on the OS.
86_async2
All tasks must be awaited or canceled. This includes Groups, Select and others.
A good pattern is right after the async/concurrent call do defer future.cancel() (assumes void return type).
That will of course change depending on the return type, you can discard it _ = .., or if it’s an error you have handle that in some way.
In that defer is where you would clean up any related/returned resources.
That is always fine even if await or another cancel is called beforehand because subsequent awaits or cancels will just return a copy of the result.
It is excusable not to do the above in simple cases, which I think all these exercises fall under.
cancel also blocks, that is implied by it returning the result but best to be explicit about it.
93_async9
concurrent does not offer “true parallelism”, only “true concurrency”, which as a side effect of the implementation may or may not result in “true parallelism”.
95_quiz_async
only the collection task needs to be concurrent relative to the reading tasks, you can swap the which tasks are concurrent/async, as long as the concurrent task(s) are started first.
Minimising what is actually concurrent is good to allow the implementation better use of its concurrency units.
Ofc the premis is the sensors are concurrent, so meh.
You often use threads and Threaded to explain the behaviour/interchangeably with “unit of concurrency”, that is fine but…
It is worth clarifying that there are other ways for concurrency to be implemented by an Io implementation; the Evented implementation(s) for example use M:N green threading/fibres, which can provide concurrency even with a single backing OS thread.
The most important thing is to explain and ensure all futures are awaited or canceled.
perhaps provide an exercise that requires various resources be cleaned up through async/concurrent/Select for practice.