Hone logo
Hone
Problems

Asynchronous Future Trait Implementation in Rust

This challenge asks you to implement a simplified version of Rust's Future trait. Futures represent asynchronous computations that may not be immediately available. Implementing this trait allows you to build asynchronous systems, enabling concurrent operations without blocking the main thread, a crucial concept for responsive applications.

Problem Description

You are tasked with creating a Future trait that mimics the core functionality of Rust's built-in Future trait. The trait should define a single method, poll, which is responsible for checking if the future is ready and, if so, returning the result. If the future is not ready, poll should return Pending.

The poll method takes a Context argument, which provides access to a mechanism for waking up the future when it's ready. For this simplified version, we will ignore the waker functionality within the Context and always return Pending if the future is not ready. The focus is on the core poll method and the Future trait definition.

Key Requirements:

  • Define a Future trait with a poll method.
  • The poll method should accept a Context argument.
  • The poll method should return Poll::Ready(result) if the future is complete, or Poll::Pending if it is not.
  • Create a simple Context struct.
  • Create a concrete type MyFuture that implements the Future trait. MyFuture should hold a value and a timer (represented by a std::time::Duration). It should return Poll::Ready(self.value) after the specified duration, and Poll::Pending before.

Expected Behavior:

The poll method should be called repeatedly. Initially, it should return Poll::Pending. After the specified duration, it should return Poll::Ready(value).

Edge Cases to Consider:

  • What happens if the duration is zero? The future should return Poll::Ready immediately.
  • How should the Context be handled (even though we're ignoring the waker)? It should be accepted as an argument.

Examples

Example 1:

Input: MyFuture { value: 5, duration: std::time::Duration::from_secs(1) }
Output: Poll::Pending (initially) -> Poll::Ready(5) (after 1 second)
Explanation: The future is not ready immediately, so it returns Pending. After 1 second, it returns Ready(5).

Example 2:

Input: MyFuture { value: 10, duration: std::time::Duration::from_secs(0) }
Output: Poll::Ready(10)
Explanation: The duration is zero, so the future is ready immediately and returns Ready(10).

Example 3: (Complex Scenario)

Input: MyFuture { value: "Hello", duration: std::time::Duration::from_millis(500) }
Output: Poll::Pending (initially) -> Poll::Ready("Hello") (after 500 milliseconds)
Explanation: Demonstrates a string value and a shorter duration.

Constraints

  • The duration in MyFuture must be a std::time::Duration.
  • The value in MyFuture can be any type T.
  • The Context struct should have a waker field (though it's not used in the poll implementation).
  • The poll method must return either Poll::Ready(T) or Poll::Pending.
  • You must use the std::time module for time-related operations.
  • No external crates are allowed.

Notes

  • This is a simplified implementation of the Future trait. A real-world Future would involve a waker and more complex state management.
  • Focus on the core concepts of the Future trait: representing asynchronous computations and providing a mechanism for polling their completion.
  • Consider using a simple timer mechanism (e.g., std::thread::sleep) to simulate the asynchronous delay. However, be aware that std::thread::sleep blocks the current thread, which defeats the purpose of asynchronicity. For a truly non-blocking solution, you would need to use an asynchronous timer. For this exercise, std::thread::sleep is acceptable for demonstration purposes.
  • The Context struct is provided for completeness and to match the signature of the Future trait. You don't need to implement the waker functionality.
use std::time::Duration;
use std::thread;

enum Poll<T> {
    Ready(T),
    Pending,
}

struct Context {
    waker: std::sync::Mutex<Option<Box<dyn Fn()>>>, // Not used in this simplified version
}

trait Future {
    type Output;
    fn poll(self: std::pin::Pin<&mut Self>, cx: &Context) -> Poll<Self::Output>;
}

struct MyFuture<T> {
    value: T,
    duration: Duration,
}

impl<T> MyFuture<T> {
    fn new(value: T, duration: Duration) -> Self {
        MyFuture { value, duration }
    }
}

impl<T> Future for MyFuture<T> {
    type Output = T;

    fn poll(mut self: std::pin::Pin<&mut Self>, cx: &Context) -> Poll<Self::Output> {
        if self.duration == Duration::from_secs(0) {
            return Poll::Ready(self.value);
        }

        thread::sleep(self.duration);
        Poll::Ready(self.value)
    }
}
Loading editor...
rust