Draft: sleepfuture-reset: Create new SleepFuture trait with reset method
This MR resolves: #2176
We want a SleepFuture trait with reset method so we can change the expiration time of the current future without the need to create a new future. This could be handy in e.g the padding implementation. In maybenot_padding.rs:L903 we can see where this would be useful.
I placed demo-codes for each runtime in arti/examples, all seemed to run fine.
ℹ️  Demo for Tokio
use anyhow::Result;
use tor_rtcompat::{SleepProvider, SleepFuture};
use arti_client::{TorClient, TorClientConfig};
#[tokio::main]
async fn main() -> Result<()> {
    let tor_client = TorClient::create_bootstrapped(TorClientConfig::default()).await?;
    let rt = tor_client.runtime();
    println!("Set sleep for 5 seconds...");
    let mut sleep = std::pin::pin!(rt.sleep(std::time::Duration::from_secs(5)));
    println!("Reset sleep to 15 seconds (without creating new future)...");
    let new_deadline = rt.now() + std::time::Duration::from_secs(15);
    sleep.as_mut().reset(new_deadline.into());
    println!("Sleeping for 15 seconds...");
    sleep.await;
    println!("Awake after 15 seconds!");
    Ok(())
}
[package]
name = "sleepfuture-reset-example"
version = "0.1.0"
edition = "2024"
[dependencies]
anyhow = "1.0.97"
arti-client = { path = "../../crates/arti-client" }
tokio = { version = "1", features = ["macros", "rt-multi-thread", "sync"] }
tor-rtcompat = { path = "../../crates/tor-rtcompat" }ℹ️  Demo for Smol
use anyhow::Result;
use tor_rtcompat::{SleepProvider, SleepFuture, smol::SmolNativeTlsRuntime};
use arti_client::{TorClient, TorClientConfig};
fn main() -> Result<()> {
    smol::block_on(async {
        let runtime = SmolNativeTlsRuntime::create().unwrap();
        let tor_client = TorClient::with_runtime(runtime.clone())
            .config(TorClientConfig::default())
            .create_bootstrapped()
            .await?;
        let rt = tor_client.runtime();
        println!("Set sleep for 5 seconds...");
        let mut sleep = rt.sleep(std::time::Duration::from_secs(5));
        println!("Reset sleep to 15 seconds (without creating new future)...");
        let new_deadline = rt.now() + std::time::Duration::from_secs(15);
        std::pin::Pin::new(&mut sleep).reset(new_deadline.into());
        println!("Sleeping for 15 seconds...");
        sleep.await;
        println!("Awake after 15 seconds!");
        Ok(())
    })
}[package]
name = "sleepfuture-reset-example"
version = "0.1.0"
edition = "2024"
[dependencies]
anyhow = "1.0.97"
arti-client = { path = "../../crates/arti-client", features = ["smol"] }
smol = "2.0.2"
tor-rtcompat = { path = "../../crates/tor-rtcompat" }ℹ️  Demo for async-std
use anyhow::Result;
use tor_rtcompat::{SleepProvider, SleepFuture, async_std::AsyncStdNativeTlsRuntime};
use arti_client::{TorClient, TorClientConfig};
#[async_std::main]
async fn main() -> Result<()> {
    let runtime = AsyncStdNativeTlsRuntime::create().unwrap();
    let tor_client = TorClient::with_runtime(runtime.clone())
        .config(TorClientConfig::default())
        .create_bootstrapped()
        .await?;
    let rt = tor_client.runtime();
    println!("Set sleep for 5 seconds...");
    let mut sleep = rt.sleep(std::time::Duration::from_secs(5));
    println!("Reset sleep to 15 seconds (with emulating resetting current future)...");
    let new_deadline = rt.now() + std::time::Duration::from_secs(15);
    std::pin::Pin::new(&mut sleep).reset(new_deadline.into());
    println!("Sleeping for 15 seconds...");
    sleep.await;
    println!("Awake after 15 seconds!");
    Ok(())
}[package]
name = "sleepfuture-reset-example"
version = "0.1.0"
edition = "2024"
[dependencies]
anyhow = "1.0.97"
arti-client = { path = "../../crates/arti-client", features = ["async-std"] }
async-std = { version = "1.13", features = ["attributes"] }
tor-rtcompat = { path = "../../crates/tor-rtcompat" }Edited  by Niel Duysters