I recently started working with Rust async. The main issue I am currently facing is code duplication: I have to duplicate every function that I want to support both asynchronous and blocking APIs. This could be great to have a `maybe-async`. I took a look at the available crates to work around this (maybe-async, bisync), but they all have issues or hard limitations.
It'll depend immensely on what you're actually doing, but if it's simple enough you may be able to make a macro that subs out the types & awaits
Async Rust never left the MVP state
221–230 of 273 posts
Re: Async Rust never left the MVP state
#222Earlier quoted context omitted.
Because foo might call process::abort().
I disagree. If the codegen / optimizer is trying to preserve the rule that futures don’t have side effects until polled, then it seems fine to assume that the future being wrapped also follows that rule. So if I call a foo() that violates the rule, it seems odd to complain that the generated bar() also violates it.
Re: Async Rust never left the MVP state
#223Re: Async Rust never left the MVP state
#224Async seems like an underbaked idea across the board. Regular code was already async. When you need to wait for an async operation, the thread sleeps until ready and the kernel abstracts it away. But We didn’t like structuring code into logical threads, so we added callback systems for events. Then realized callbacks are very hard to reason about and that sequential control is better. So threads was the right program…
You don’t have threads on embedded, but you want a way to express concurrent waiting. Different problems altogether
Re: Async Rust never left the MVP state
#225Re: Async Rust never left the MVP state
#226Re: Async Rust never left the MVP state
#227Earlier quoted context omitted.
Threads are a scheduling model that delegates to the OS scheduler. Async style provides a primitive for creating a custom scheduler but is not a scheduler per se. To use a custom scheduler you must first disable the existing schedulers your code is using by default for both execution and I/O. That means no OS scheduling. Thread-per-core architectures with static allocation and direct userspace I/O is the idiomatic wa…
That’s not what I asked.
What does "I/O optimized scheduling" look like to you, and does it end up with the same sort of compiler hints, like "async / await"? Or is it different?
Re: Async Rust never left the MVP state
#228Earlier quoted context omitted.
Can you elaborate on this please? Do you mean that’s basically impossible for rust std to provide a default runtime that makes “everyone” (embedded on one end and web on the other) happy?
I think that's the problem in essence, yes. Different executors built on top of different primitives and having different executions strategies will have mutually incompatible constraints. To spawn a future on tokio, it has to implement `Send`, because tokio is a work-stealing executor. That isn't the case for monoio or other non-work-stealing async executors, where tasks are pinned to the thread they are spawned on…
Tokio's default executor is a work-stealing multi-threaded executor, but it also has a local executor and a current-thread executor, which can run !Send futures.
Re: Async Rust never left the MVP state
#229Earlier quoted context omitted.
That’s part of it. Then you add a thread pool to dispatch your tasks into to mitigate the cost of a thread start. Then you run into blocking problems and are like “I wish I had some keyword to express when a function needed to be run on the thread pool”. Then you’ve done a speed run of the past 40 years of research.
The 40 years of research was actually in OS theory so that you could write normal code and async was abstracted away. A thread pool is not a research project.
* Cooperative vs. preemptive scheduling
* Userspace vs. kernel scheduling
* Stackless vs. stackful
* Easy control over waiting/blocking behavior vs. none
* Easy fan out + join vs. maybe, with some work and thread spawn overhead
* Can integrate within a single-threaded event loop vs. not really
Depending on what you're doing they may be interchangeable or you can only go one way. The basic cases where you're doing basically synchronous work in a thread/task is no different either way, other than having colored functioned with async/await and efficiency. If you're doing some UI work then event handlers are likely running in a single-threaded event loop which is the only thread you can interact with the UI on, which you can't block or the UI is going to freeze.
Re: Async Rust never left the MVP state
#230Earlier quoted context omitted.
I think that callbacks are actually easier to reason about: When it comes time to test your concurrent processing, to ensure you handle race conditions properly, that is much easier with callbacks because you can control their scheduling. Since each callback represents a discrete unit, you see which events can be reordered. This enables you to more easily consider all the different orderings. Instead with threads it…
I agree. I don’t think callbacks are an underbaked language feature.