Crate whorl

source ·
Expand description

A Whorlwind Tour in Building a Rust Async Executor

构建Rust异步执行器的Whorlwind之旅

whorl is a self contained library to run asynchronous Rust code with the following goals in mind: whorl是一个自包含的库,用于运行具有以下目标的异步Rust代码:

  • Keep it in one file. You should be able to read this code beginning to end like a literate program and understand what each part does and how it fits into the larger narrative. The code is organized to tell a story, not necessarily how I would normally structure Rust code. 仅有一个文件,您应该能够从头到尾阅读这段代码,就像一个文学程序一样,了解每个部分的作用以及它如何融入到更大的叙事中。 代码被组织成一个故事,而不是我通常如何组织Rust代码。

  • Teach others what is going on when you run async code in Rust with a runtime like tokio. There is no magic, just many synchronous functions in an async trench coat. 这向你展示了当你在tokio这样的运行时中运行Rust异步代码时到底发生了什么。没有魔法,在异步外表下只有许多同步函数。

  • Explain why different runtimes are incompatible, even if they all run async programs. 解释为什么不同的运行时是不兼容的,即使它们都能运行异步程序。

  • Only use the std crate to show that yes all the tools to build one exist and if you wanted to, you could. 仅使用std crate来实现,所有用于实现的工具都是,如果你想的话,你也可以。

  • Use only stable Rust. You can build this today; no fancy features needed. 仅使用稳定的Rust。你可以今天就构建它,不需要任何花哨的功能。

  • Explain why std doesn’t ship an executor, but just the building blocks. 解释为什么std不会提供一个执行器,而只是提供构建块。

What whorl isn’t: whorl不是:

  • Performant, this is an adaptation of a class I gave at Rustconf a few years back. Its first and foremost goal is to teach how an executor works, not the best way to make it fast. Reading the tokio source code would be a really good thing if you want to learn about how to make things performant and scalable. 不是有效的,这是我在几年前在Rustconf上给出的一个类的适配。 它的首要目标是教授执行器如何工作,而不是使其快速的最佳方法。 如果你想了解如何使事情变得高效和可扩展,那么阅读tokio源代码将是一个非常好的事情。

  • “The Best Way”. Programmers have opinions, I think we should maybe have less of them sometimes. Even me. You might disagree with an API design choice or a way I did something here and that’s fine. I just want you to learn how it all works. 不是“最佳方式”。程序员有自己的观点,我认为我们有时应该减少一些观点。甚至是我。 你可能会对API设计选择或我在这里做的事情的方式产生不同意见,这很好。 我只是想让你了解它是如何工作的。

  • An introduction to Rust. This assumes you’re somewhat familiar with it and while I’ve done my best to break it down so that it is easy to understand, that just might not be the case and I might gloss over details given I’ve done Rust for over 6 years at this point. Expert blinders are real and if things are confusing, do let me know in the issue tracker. I’ll try my best to make it easier to grok, but if you’ve never touched Rust before, this is in all honesty not the best place to start. 不是Rust的介绍。这假设你对它有一定的了解,虽然我已经尽力将其分解,使其易于理解,但这可能并不是这样, 而且我可能会忽略细节,因为我已经在这里做了6年多的Rust。 专家盲目是真实的,如果事情令人困惑,请在issue中告诉我。 我会尽力让它更容易理解,但如果你从未接触过Rust,那么老实说,这不是开始的最佳地方。

With all of that in mind, let’s dig into it all! 请记住这一点,让我们深入了解它!

Modules

  • This is our module to provide certain kinds of futures to users. In the case of our Sleep future here, this is not dependent on the runtime in particular. We would be able to run this on any executor that knows how to run a future. Where incompatibilities arise is if you use futures or types that depend on the runtime or traits not defined inside of the standard library. For instance, std does not provide an AsyncRead/AsyncWrite trait as of Oct 2021. As a result, if you want to provide the functionality to asynchronously read or write to something, then that trait tends to be written for an executor. So tokio would have its own AsyncRead and so would ours for instance. Now if a new library wanted to write a type that can, say, read from a network socket asynchronously, they’d have to write an implementation of AsyncRead for both executors. Not great. Another way incompatibilities can arise is when those futures depend on the state of the runtime itself. Now that implementation is locked to the runtime. 这是我们的模块所使用到的一些future。Sleep future不依赖于特定的运行时。我们可以在任何执行器上运行它。 不兼容的地方在于,如果您使用依赖于运行时或标准库中未定义的特性的future或类型,则会出现不兼容的情况。 例如,std截至2021年10月还没有提供AsyncRead/AsyncWritetrait。 因此,如果您想提供异步读取或写入某些内容的功能,则该trait需要为执行器实现。 因此,tokio将拥有它自己的AsyncRead,我们也将拥有自己的AsyncRead。 现在,如果一个新的库想要写一个类型,可以异步地从网络套接字读取,那么他们就必须为两个执行器编写AsyncRead的实现。 另一种不兼容的情况是,当这些future依赖于运行时本身的状态时,该实现将被锁定到运行时。