

Rust's Future: Internal Execution - Knoldus Blogs
source link: https://blog.knoldus.com/rusts-future-internal-execution/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

As you all know Rust Programming has Future
s which helps to make our code Asynchronous. Rust's Futures are analogous to Promises
.
This article mainly pertains to the internal working of the Future
and we’ll also understand the structure of the Future like how it is defined and how it will execute when it comes into the action.
Future: In a Nutshell
Future is trait in Rust Programming Language
and it represents an asynchronous computation. Future
s allow you to write a code that can be run asynchronously.
Rust’s Future
s are always Results that means you have to specify both the expected return type and the alternative error one.
With the help of this, we can chain functions onto the result, then we can transform it, handle errors, can join with other futures as well.
It is a concept for an object which is a proxy for another value that may not be ready yet
.
Future: When to use
Let’s consider a scenario, where you have multiple jobs in your program. And as you already know that Rust is a synchronous language, so it waits until the first job to complete then will it execute the next job. So this is the scenario where you can use Futures and make your program asynchronous. By telling the compiler like “Hey there are multiple jobs to execute, so instead of waiting for the first job to complete let’s jump to the other jobs asynchronously“.
There are many reasons why we might want to use a future instead of a standard function: performance, elegance, composability, and so on.
I guess, now we all are familiar with Rust’s Futures, and when to use Futures.
Now, let’s understand the internal execution of Futures.
Future: Internals
Let’s create simple Future.
trait Future {
type Output;
fn poll(&mut self, wake: fn()) -> Poll<Self::Output>;
}
enum Poll<T> {
Ready(T),
Pending,
}
As this is the simple signature of the Future
trait, however, the actual Rust’s Future has a slightly different signature or you can say, that Future has some advanced approach that helps in the scenario of immovability and managing all the contexts separately.
Let’s understand each point one by one:
We have a trait
called the Future which contains type
and function
.
type Output
: it is self-explanatory that Future trait has a type called as Output.fn poll(&mut self, wake: fn()) -> Poll<Self::Output>
:
a simple function has two parameters and which returns anenum
.Poll<T>
: anenum
withReady<T>
andPending
.
This poll
function is a major part of the future. It actually starts the flow of asynchronous execution, like if the Future
completes, it returns Poll::Ready(T)
. If the future is not able to complete yet, it returns Poll::Pending
and arranges for the wake()
function to be called when the Future
is ready to make more progress.
And wake
function also plays an important role in the Future
.
Wake tells the executor
which futures are ready to be poll
ed and without it the executor
would not be able to get the information about which Future
could make progress and then executor
would have to poll all the Future
s constantly.
Hope you all get what actually happens under the hood in the Future
s. Now let’s understand this execution more clearly by implementing a small piece of code.
// This is our structure with one member `count`.
struct SimpleData {
count: u32,
}
// Let's implement the Future for this SimpleData
impl Future for SimpleData {
type Output = u32;
fn poll(&mut self, wake: fn()) -> Poll<Self::Output> {
if self.count == 10 {
Poll::Ready(self.count)
} else {
// The count does not reach it's desired value yet which is 10.
// Let's increment the value by one.
self.count() += 1;
// set the `wake` function as a callback as our Future is not resolved yet.
// Rust's Future uses Context in place of function pointer (fn()) which provides the type waker.
// Waker internally implements `clone()` so that it can be copied.
// It helps the executor to woke up the task for the current Future.
wake;
Poll::Pending
}
}
}
In the about example we just implemented the internal functionality of the Future
. It won’t compile, it is just to understand the internals of the Future
. The major role is driven by poll()
method which actually returns the resolved Future
by returning the Poll::Ready
or invokes the wake
by returning the Poll::Pending
.
Now let’s understand the code:
- Firstly we have created a structure with a counter.
- Then we have implemented the Future trait for our structure.
- In the
poll()
‘s implementation, we have provided the condition. - If count equals 10 then we are returning a
Poll::Ready
response with the value, 10. - And if the count does not equals to 10 then we are incrementing the count and returning
Poll::Pending
Here wake
plays an important role as the official Rust’s Future uses the Content in place of function pointer (fn()). The Context provides the type Waker
.
Future: Waker
Waker
provides a wake()
method that can be used to tell the executor that the associated task should be awoken. When wake()
is called, the executor knows that the task associated with the Waker
is ready to make progress, and its future should be polled again.
Hope you got some insights for the internal working of the Asynchronous Program.
Thanks for reading!!!
If you want to read more content like this? Subscribe Rust Times Newsletter and receive insights and latest updates, bi-weekly, straight into your inbox. Subscribe Rust Times Newsletter: https://bit.ly/2Vdlld7 .
Video: Learn more and enhance your knowledge and skills of Rust Language by subscribing Rust Times newsletter and receive updates bi-weekly. https://bit.ly/2Vdlld7 .
Template: For more such template updates, subscribe Rust Times Newsletter: https://bit.ly/2Vdlld7
Recommend
-
7
Don't Worry... I hugged it first Reading Time: 2 minutes Loggers play the most significant role in the software development community that not all developers take it seriously. Due to this, all have lost countle...
-
12
Implement 'unimplemented' feature of Rust Reading Time: 2 minutes The headline looks weird. Isn’t it. Well, there are some hidden corals in Rust sea, which you won’t find in Rust documentation. In the continuati...
-
2
Completable Future Improvements in Java9 Reading Time: 3 minutesIn this article, I will be talking about the improvements...
-
17
Knoldus Blogs Reading Time: 3 minutesIn my previous blog, we discussed how Rust performs memory management. Interesting as it is, the concept of ownership d...
-
10
Substrate – A Blockchain Framework on Rust Knoldus Blog Audio Reading Time: 3 minute...
-
9
The Relation between "Rust and Safe Programming" !! Knoldus Blog Audio Reading Time: 5 minutes The Rust
-
5
Lifetime in Rust – Part 1 Reading Time: 4 minutesRust can be a tricky language to work with and one of the prime reasons f...
-
5
Embedded-Rust: Let’s start with STM32F3DISCOVERY Reading Time: 5 minutes An embedded system is computer hardware with soft...
-
6
Working with Loop, While, For Reading Time: 2 minutesI hope you have already been through the following blogs in order to learn control flow and iteration in RUST: Basically, RUST is no different compare...
-
12
Apache Spark’s Join Algorithms Reading Time: 4 minutes One of the most frequently used transformations in Apache Spark is...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK