diff --git a/src/1_futures_in_rust.md b/src/1_futures_in_rust.md index 6e056b0..b93d2cf 100644 --- a/src/1_futures_in_rust.md +++ b/src/1_futures_in_rust.md @@ -231,7 +231,7 @@ Futures, but we're not gonna stop yet, there are lots of details to cover. Take a break or a cup of coffee and get ready as we go for a deep dive in the next chapters. -## Bonus section +## Want to learn more about concurrency and async? If you find the concepts of concurrency and async programming confusing in general, I know where you're coming from and I have written some resources to @@ -250,7 +250,61 @@ I'll be right here when you're back. However, if you feel that you have the basics covered, then let's get moving! +## Bonus section - additional notes on Futures and Wakers + +> In this section we take a deeper look at some advantages of having a loose +coupling between the Executor-part and Reactor-part of an async runtime. + +Earlier in this chapter, I mentioned that it is common for the +executor to create a new Waker for each Future that is registered with the +executor, but that the Waker is a shared object similar to a `Arc`. One of +the reasons for this design is that it allows different Reactors the +ability to Wake a Future. + +As an example of how this can be used, consider how you could create a new type +of Future that has the ability to be canceled: + +One way to achieve this would be to add an +[`AtomicBool`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html) +to the instance of the future, and an extra method called `cancel()`. The +`cancel()` method will first set the +[`AtomicBool`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html) +to signal that the future is now canceled, and then immediately call instance's +own copy of the Waker. + +Once the executor starts executing the Future, the +_Future_ will know that it was canceled, and will do the appropriate cleanup +actions to terminate itself. + +The main reason for designing the Future in this manner is because we don't have +to modify either the Executor or the other Reactors; they are all oblivious to +the change. + +The only possible issue is with the design of the Future itself; a +Future that is canceled still needs to terminate correctly according to the +rules outlined in the docs for +[`Future`](https://doc.rust-lang.org/std/future/trait.Future.html). That means +that it can't just delete it's resources and then sit there; it needs to return +a value. It is up to you to decide if a canceled future will return +[`Pending`](https://doc.rust-lang.org/std/task/enum.Poll.html#variant.Pending) +forever, or if it will return a value in +[`Ready`](https://doc.rust-lang.org/std/task/enum.Poll.html#variant.Ready). Just +be aware that if other Futures are `await`ing it, they won't be able to start +until [`Ready`](https://doc.rust-lang.org/std/task/enum.Poll.html#variant.Ready) +is returned. + +A common technique for cancelable Futures is to have them return a +Result with an error that signals the Future was canceled; that will permit any +Futures that are awaiting the canceled Future a chance to progress, with the +knowledge that the Future they depended on was canceled. There are additional +concerns as well, but beyond the scope of this book. Read the documentation and +code for the [`futures`](https://crates.io/crates/futures) crate for a better +understanding of what the concerns are. + +>_Thanks to [@ckaran](https://github.com/ckaran) for contributing this bonus segment._ + [async_std]: https://github.com/async-rs/async-std [tokio]: https://github.com/tokio-rs/tokio [compat_info]: https://rust-lang.github.io/futures-rs/blog/2019/04/18/compatibility-layer.html [futures_rs]: https://github.com/rust-lang/futures-rs + diff --git a/src/2_a_mental_model_for_futures.md b/src/2_a_mental_model_for_futures.md index 69cf37b..3792b88 100644 --- a/src/2_a_mental_model_for_futures.md +++ b/src/2_a_mental_model_for_futures.md @@ -12,9 +12,6 @@ build upon. Finally, please note that the code itself is "pseudo-rust" due to the need for brevity and clarity. >Click on a page to open a larger view of it in a new tab. -> ->_Thanks to [@ckaran](https://github.com/ckaran) for feedback and [discussions](https://github.com/cfsamson/books-futures-explained/issues/25) on -this chapter._ slide1 diff --git a/src/conclusion.md b/src/conclusion.md index e8eb289..17d6dec 100644 --- a/src/conclusion.md +++ b/src/conclusion.md @@ -11,45 +11,6 @@ I'll leave you with some suggestions for exercises if you want to explore a litt Until next time! -## Further notes and comments - -In [Chapter 2](1_futures_in_rust.md), I mentioned that it is common for the -executor to create a new Waker for each Future that is registered with the -executor, but that the Waker is a shared object similar to a `Arc`. One of -the reasons for this design is that it allows different Reactors the ability to -Wake a Future. As an example of how this can be used, consider how you could -create a new type of Future that has the ability to be canceled. A method of -doing this would be to add an -[`AtomicBool`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html) -to the instance of the future, and an extra method called `cancel()`. The -`cancel()` method will first set the -[`AtomicBool`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html) -to signal that the future is now canceled, and then immediately call instance's -own copy of the Waker. Once the executor starts executing the Future, the -_Future_ will know that it was canceled, and will do the appropriate cleanup -actions to terminate itself. - -The main reason for designing the Future in this manner is because we don't have -to modify either the Executor or the other Reactors; they are all oblivious to -the change. The only possible issue is with the design of the Future itself; a -Future that is canceled still needs to terminate correctly according to the -rules outlined in the docs for -[`Future`](https://doc.rust-lang.org/std/future/trait.Future.html). That means -that it can't just delete it's resources and then sit there; it needs to return -a value. It is up to you to decide if a canceled future will return -[`Pending`](https://doc.rust-lang.org/std/task/enum.Poll.html#variant.Pending) -forever, or if it will return a value in -[`Ready`](https://doc.rust-lang.org/std/task/enum.Poll.html#variant.Ready). Just -be aware that if other Futures are `await`ing it, they won't be able to start -until [`Ready`](https://doc.rust-lang.org/std/task/enum.Poll.html#variant.Ready) -is returned. A common technique for cancelable Futures is to have them return a -Result with an error that signals the Future was canceled; that will permit any -Futures that are awaiting the canceled Future a chance to progress, with the -knowledge that the Future they depended on was canceled. There are additional -concerns as well, but beyond the scope of this book. Read the documentation and -code for the [`futures`](https://crates.io/crates/futures) crate for a better -understanding of what the concerns are. - ## Reader exercises So our implementation has taken some obvious shortcuts and could use some improvement. diff --git a/src/introduction.md b/src/introduction.md index 49195a7..616c202 100644 --- a/src/introduction.md +++ b/src/introduction.md @@ -64,6 +64,8 @@ A special thanks to [jonhoo](https://twitter.com/jonhoo) who was kind enough to give me some valuable feedback on a very early draft of this book. He has not read the finished product, but a big thanks is definitely due. +Thanks to [@ckaran](https://github.com/ckaran) for feedback and discussions on chapter 2 and 3. + ## Translations [This book has been translated to Chinese](https://stevenbai.top/rust/futures_explained_in_200_lines_of_rust/) by [nkbai](https://github.com/nkbai).