Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

It's certainly possible to pave over the difference between models to a certain extent, but the resulting solution will not be zero-cost.

Yes, there is a fundamental difference between those models (otherwise we would not have two separate models).

In a poll-based model interactions between task and runtime look roughly like this:

- task to runtime: I want to read data on this file descriptor.

- runtime: FD is ready, I'll wake-up the task.

- task: great, FD is ready! I will read data from FD and then will process it.

While in a completion based model it looks roughly like this:

- task to runtime: I want data to be read into this buffer which is part of my state.

- runtime: the requested buffer is filled, I'll wake-up the task.

- task: great requested data is in the buffer! I can process it.

As you can see the primary difference is that in the latter model the buffer becomes "owned" by runtime/OS while task is suspended. It means that you can not simply drop a task if you no longer need its results, like Rust currently assumes. You have either wait for the data read request to complete or to (possibly asynchronously) request cancellation of this request. With the current Rust async if you want to integrate with io-uring you would have to use awkward buffers managed by runtime, instead of simple buffers which are part of the task state.

Even outside of integration with io-uring/IOCP we have use-cases which require async Drop and we currently don't have a good solution for it. So I don't think that the decision to allow dropping tasks without an explicit cancellation was a good one, even despite the convenience which it brings.



FWIW, I'd bet almost anything that this problem isn't solvable in any general way without linear types, at which point I bet it would be a somewhat easy modification to what Rust has already implemented. (Most of my development for a long time now has been in C++ using co_await with I/O completion and essentially all of the issues I run into--including the things analogous to "async Drop", which I would argue is actually the same problem as being able to drop a task itself--are solvable using linear types, and any other solutions feel like they would be one-off hacks.) Now, the problem is that the Rust people seem to be against linear types (and no one else is even considering them), so I'm pretty much resigned that I'm going to have to develop my own language at some point (and see no reason to go too deep into Rust in the mean time) :/.


I did a double take seeing your username above this comment!

Thank you for your contributions to the jailbreak community, it’s what got me started down the programming / tinkering path back in middle school and has significantly shaped the opportunities I have today. Can’t believe I’m at the point where I encountered you poking around the same threads on a forum... made my day! :)


> at which point I bet it would be a somewhat easy modification to what Rust has already implemented.

You'd lose that bet: https://gankra.github.io/blah/linear-rust/


This is an article about why linear types are hard to implement... and it doesn't even claim they can't be done; regardless, I have argued this at you before :(.

https://news.ycombinator.com/item?id=23579426

I continue to believe that the strongest point in that article is actually the third footnote, which correctly admits that this is mostly about a lack of appreciation.

> The Swift devs have basically the exact same argument for move-only code, and their implicit Copy bound. Hooray!

My claim here is that, given linear types, it should be trivial to use async/await style coroutines for I/O continuation. You have given no evidence against this idea.


Ah! I misunderstood you, sorry. I thought you were saying that linear types would be easy to implement. I wasn't trying to say anything about the stuff you'd do with them if you had them.


> FWIW, I'd bet almost anything that this problem isn't solvable in any general way without linear types

I think this part of your comment is absolutely right and it's fatal to the argument that Rust made the wrong decision about I/O models for Rust. Maybe in the context of some other language, Rust's decision was not the best one, but not for Rust, because Rust just doesn't have linear types.


I'm not familiar with linear types but as far as I can see they're pretty much the same as rust's ownership rules. Is there something I'm missing?


Rust implements affine types, which means every object must be used at most once. You cannot use them twice, but you can discard them and not do anything with them. Linear types means exactly once.

but I don't think you can easily move from affine types to linear types in the case of Rust, see leakpocalypse[1]

[1]: https://cglab.ca/~abeinges/blah/everyone-poops/#leakpocalyps...


ATS has linear types.


How does this proposal address the problems with "blocking on drop does not work" here? https://without.boats/blog/io-uring/

The problem here is not with Rust's async design. It's that Rust has affine types and not linear types. This is not something that could have been solved with more work on the design. It is not that there was "a decision" to allow dropping tasks; it's a constraint on the design that the language requires. (Personally, I'm unsure as to whether a practical language with true linear types is possible, but it's worth experimenting with. Rust is not and never will be that language, however.)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: