Let's quickly talk about async versus threads because they are different.
Threads are suitable for a small number of tasks.
Since threads come with CPU and memory overhead.
When we spawn and switch between threads, that is an expensive request and even idle threads can consume
resources.
Threads also allow us to use asynchronous code without huge changes.
So that is a benefit to threads.
Async, on the other hand, provides us with significantly reduced CPU and memory overhead, especially
when talking about high input and output bound tasks such as databases and servers.
You can have a significantly higher amount of tasks than operating system threads because async uses
a small amount of expensive threads to handle a large amount of cheap tasks.
But again, async does not mean it is better than threads.
It is just different.
So use threads where appropriate as well as using async.
But now let's start to get into the asynchronous programming by looking at a trait called future.
And a future is at the heart of asynchronous programming.
A future is an asynchronous computation that can produce a value.
So let's look at how the future trait is implemented just so that we can get a feel for it.
So it is a trait and it's called future and it's going to have type output.
And then inside we're going to have a function called poll.
And I'm not going to get into the actual implementation of Pull because this is a high level view.
But from this, what we can see is that a it is a generic over the output and we have a function called
poll provided for us and poll is going to allow us to check on the state of the current computation.
So if we actually look inside of pull, we we can have Penn and then we'll have a mutable self.
And then we'll have a context which is a mutable context, and then poll is going to return a pole of
self
output.
And again, we don't need to worry about Penn and context in this case because this is just a high level
overview and we just want to kind of get a feel for what a future is.
So.
But the poll function is actually really important because when a computation is done, poll will return,
poll ready, poll ready.
And when the computation is not done, poll will return.
Poll pending.
And this is important for us because it allows us to use a keyword called a weight, which we will see
in a second.
So now that we kind of know what a future is, we can start to look at.
Facing an async.
We actually need to import a dependency.
So I'm just going to go ahead and delete all of this and then we can go to our cargo file and import
in async standard and then we'll say version one.
That way we get the latest version for this dependency.
And now we want to import an.
Some of the features inside of async standard.
We want file IO Prelude and task and we want these because we're going to do an asynchronous read from
a file and then assign the contents of the file to a mutable string.
Variable and then we want to output it to the terminal.
So we're going to create a function now and we actually create this function with a new keyword and
it's going to be called async, and that's going to signify that this function is asynchronous.
So we have an async function called read file and we're going to have one parameter which is going to
extract, accept a string slice to the file we want to read from and then we're going to return a result
of type string.
So we're going to open up our file.
Point to our path and then we want to await.
And this is that key word that I mentioned a couple of minutes ago.
And I will break down a weight in a second for us.
So we're also going to have mutable contents, which is going to be the variable that stores the data
in our file.
And then we want to read to string and assign it to the contents variable.
And we also want to await that.
And then if all goes well, we want to return our.
Contents.
So what does a weight do?
Because we keep talking about it.
So what does it actually do?
Well, a weight is actually going to do what it sounds like it will do.
It is going to wait until the requested action is finished.
So a weight is essentially a marker or a bookmark, if you will.
The code will wait for a future to produce its value.
So what is the benefit to this?
Well, the runtime in charge of executing this piece of code will take care of all the other things
it can do while it waits for the computation to finish.
And then it will come back to this point, a.k.a the bookmark when the operation has finished.
So how can we put all this to use?
Well, we will find out in the next lecture when we start to talk about tasks.