codingstuff.io
ExploreTutorialsProblemsCS Subjects
Get Started
ExploreTutorialsProblemsCS Subjects
Get Started
codingstuff.io

Master the art of building software through interactive tutorials, real-world problems, and guided projects.

Pune, Maharashtra, India

codingstuffmail@gmail.com

Product

  • Explore
  • Tutorials
  • Problems
  • CS Subjects

Company

  • About
  • Contact
  • Privacy Policy
  • Terms & Conditions
  • Sitemap

© 2026 codingstuff.io. All rights reserved.

Built with ❤️ for developers everywhere

/
/
All Tutorials
🦀

Rust

27 / 58 topics
26Async Programming27Futures28Tokio Runtime
Tutorials/Rust/Futures
🦀Rust

Futures

Updated 2026-05-15
10 min read

Futures

Introduction

In the world of asynchronous programming, futures are a fundamental concept that allows you to represent values that may not be available yet but will be in the future. Rust's std::future module provides powerful tools for working with futures, enabling you to write efficient and expressive concurrent code.

Futures in Rust are lightweight abstractions that represent asynchronous computations. They allow you to perform operations without blocking the main thread, which is crucial for building responsive applications. Understanding how futures work is essential for leveraging Rust's concurrency model effectively.

Concept

At its core, a future is an object representing a value that may not be available yet but will be at some point in the future. Futures are lazy by default, meaning they only start executing when polled or awaited.

Key Characteristics of Futures

  1. Lazy Evaluation: Futures do not execute immediately upon creation. They only begin execution when they are polled.
  2. Polling: The process of checking whether a future has completed is called polling. When you poll a future, it returns one of three states:
    • Pending: The future is still in progress and needs to be polled again later.
    • Ready(value): The future has completed successfully, and the value is available.
    • Err(error): The future encountered an error during execution.
  3. Asynchronous Execution: Futures allow you to perform operations asynchronously without blocking the main thread.

Future Trait

In Rust, futures are represented by the Future trait, which requires implementing a single method: poll. Here's a simplified version of the Future trait:

Rust
1trait Future {
2 type Output;
3
4 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
5}
  • type Output: Defines the type of value that the future will produce when it completes.
  • poll method: This method is responsible for driving the future's execution. It takes a mutable reference to self, pinned (Pin<&mut Self>), and a context (&mut Context<'_>). The method returns a Poll<Self::Output>, which can be either Pending or Ready(value).

Examples

Let's explore some practical examples to understand how futures work in Rust.

Basic Future Example

First, let's create a simple future that completes after a certain duration:

Rust
1use std::future::Future;
2use std::pin::Pin;
3use std::task::{Context, Poll};
4use std::time::{Duration, Instant};
5use tokio::time::sleep;
6
7struct Delay {
8 when: Instant,
9}
10
11impl Future for Delay {
12 type Output = &'static str;
13
14 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
15 if Instant::now() >= self.when {
16 Poll::Ready("Done!")
17 } else {
18 cx.waker().wake_by_ref();
19 Poll::Pending
20 }
21 }
22}
23
24#[tokio::main]
25async fn main() {
26 let when = Instant::now() + Duration::from_secs(1);
27 let delay = Delay { when };
28
29 println!("Waiting for the future to complete...");
30 let result = delay.await;
31 println!("{}", result); // Output: Done!
32}

In this example, we define a Delay struct that implements the Future trait. The poll method checks if the current time has reached the specified duration. If it has, the future completes with the message "Done!". Otherwise, it schedules itself to be polled again by waking the waker.

Using Tokio's sleep

Tokio is a popular asynchronous runtime for Rust that provides utilities like sleep, which returns a future that completes after a specified duration:

Rust
1use tokio::time::{sleep, Duration};
2
3#[tokio::main]
4async fn main() {
5 println!("Sleeping for 2 seconds...");
6 sleep(Duration::from_secs(2)).await;
7 println!("Woke up!");
8}

In this example, we use Tokio's sleep function to create a future that completes after 2 seconds. The await keyword is used to asynchronously wait for the future to complete.

Combining Futures

Futures can be combined using combinators like join, which allows you to wait for multiple futures concurrently:

Rust
1use tokio::time::{sleep, Duration};
2use futures::future::join;
3
4#[tokio::main]
5async fn main() {
6 let future1 = async {
7 sleep(Duration::from_secs(2)).await;
8 "Future 1 completed"
9 };
10
11 let future2 = async {
12 sleep(Duration::from_secs(1)).await;
13 "Future 2 completed"
14 };
15
16 let (result1, result2) = join(future1, future2).await;
17
18 println!("{}", result1); // Output: Future 1 completed
19 println!("{}", result2); // Output: Future 2 completed
20}

In this example, we create two futures that complete after different durations. The join combinator is used to wait for both futures concurrently and retrieve their results.

What's Next?

Understanding futures is just the beginning of Rust's asynchronous programming capabilities. In the next section, we will explore the Tokio Runtime, which provides a robust framework for building scalable and efficient asynchronous applications in Rust.

By mastering futures and Tokio, you'll be well-equipped to write high-performance, concurrent code that leverages Rust's powerful type system and safety guarantees.


PreviousAsync ProgrammingNext Tokio Runtime

Recommended Gear

Async ProgrammingTokio Runtime