Is `Futures` just a thin wrapper of thread?

I'm reading the rust async book, and notice in the first example timer futures, it used a separate thread to waite for the timer's state changing.

I myself is trying to implement a waiting-for-udp-reply Future by taking the above example as a reference and haven't yet figured out a method without spawning another thread.

So my question is that is another thread necessary under the hood of Futures?
Or in most conditions, a separate thread is a "standard procedure"?

No. Not at all. Async is for concurrency: executing many tasks interleaved in time, each giving up control flow when it can't make progress right away, so that the individual tasks don't block each other even when they use the same thread. This is useful when the bottleneck in a problem is waiting for I/O.

In contrast, threads are for parallelism: actually doing work simultaneously, likely on many physical cores, at physically the same time. This is useful when the bottleneck is performing number crunching, keeping the CPU busy with heavy work.

As they sometimes say: threads work in paralallel, async tasks wait in parallel.

The timer example likely uses a separate thread because it makes the code much simpler and the concepts easier to explain. In real code, you probably wouldn't spin up an entire thread just to wait for a timer.

5 Likes

In the model of Futures, when the task is finished, the Waker::wake is called by some entity.

The fn poll is a non-block function so it is not called inside the poll. Shouldn't wake be called in another thread? If not what could perform the calling to the wake?

Please forgive my ignorance and thank you for your reply.

You don't need to trigger the waker in another thread. A Waker is a glorified callback that could be called from anywhere, possibly even the poll() method for a different future.

2 Likes

Waker::wake can also be called from "Outside" your code (given some C bindings). Examples for this would usually be that the operating system calls the Method on its own after the IO Operation finished or the method is called by an interrupt (this usually happens when doing embedded stuff)

2 Likes

Here are some examples where wake might be called on the same thread:

  1. Using a message passing channel. The sender calls wake on the receiver's waker. Both futures could run on the same thread.
  2. Using the tokio::net IO types. The Tokio runtime has what it calls an IO driver. The IO driver is a collection of all pending IO operations, and Tokio will check it for new events and call wake on the appropriate wakers between polling tasks.
  3. Using the tokio::time types. Same story as tokio::net. Tokio has a big collection of timers, and between polling tasks, it will call wake on the various timers.
6 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.