Repository: tokio-rs/tokio
File: tokio/src/runtime/handle.rs (Rust)

Code before:
    #[track_caller]
    pub fn current() -> Self {
        Handle {
            inner: scheduler::Handle::current(),
        }
    }

    /// Returns a Handle view over the currently running Runtime
    ///
    /// Returns an error if no Runtime has been started
    ///
    /// Contrary to `current`, this never panics
    pub fn try_current() -> Result<Self, TryCurrentError> {
        context::with_current(|inner| Handle {
            inner: inner.clone(),
        })
    }

    /// Spawns a future onto the Tokio runtime.
    ///
    /// This spawns the given future onto the runtime's executor, usually a
    /// thread pool. The thread pool is then responsible for polling the future
    /// until it completes.
    ///
    /// Executes the given future. Depending on the current [`crate::runtime::Runtime`],
    /// it may start immediately in the background or require blocking on the [`JoinHandle`].
    ///
    /// See [module level][mod] documentation for more details.
    ///
    /// [mod]: index.html
    ///
    /// # Examples
    ///
    /// ```
    /// # #[cfg(not(target_family = "wasm"))]
    /// # {
    /// use tokio::runtime::Runtime;
    ///
    /// # fn dox() {
    /// // Create the runtime
    /// let rt = Runtime::new().unwrap();
    /// // Get a handle from this runtime
    /// let handle = rt.handle();
    ///
    /// // Spawn a future onto the runtime using the handle
    /// handle.spawn(async {
    ///     println!("now running on a worker thread");
    /// });
    /// # }
    /// # }
    /// ```

Review comment (bug):
> or require blocking on the [`JoinHandle`]

For the current thread runtime, `join_handle.await` doesn't execute the task if there is no thread is executing the `rt.block_on`. 

Here is an example.

```rust
use std::{thread::sleep, time::Duration};
use tokio::runtime;

fn main() {
    use tokio::task;

    let rt = runtime::Builder::new_current_thread().build().unwrap();

    println!("RT");
    let join_handle: task::JoinHandle<_> = rt.spawn(async {
        println!("JOB");
        // some work here
    });

    println!("SLEEP");
    sleep(Duration::from_secs(5));
    println!("SLEEP END");

    rt.handle().block_on(join_handle).unwrap();
    println!("END");
}
```

[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=e15d5f11d0525eb78152a6a247d7cace)

Code after:
    #[track_caller]
    pub fn current() -> Self {
        Handle {
            inner: scheduler::Handle::current(),
        }
    }

    /// Returns a Handle view over the currently running Runtime
    ///
    /// Returns an error if no Runtime has been started
    ///
    /// Contrary to `current`, this never panics
    pub fn try_current() -> Result<Self, TryCurrentError> {
        context::with_current(|inner| Handle {
            inner: inner.clone(),
        })
    }

    /// Spawns a future onto the Tokio runtime.
    ///
    /// This spawns the given future onto the runtime's executor, usually a
    /// thread pool. The thread pool is then responsible for polling the future
    /// until it completes.
    ///
    /// The provided future will start running in the background immediately
    /// when `spawn` is called, even if you don't await the returned
    /// `JoinHandle` (assuming that the runtime [is running][running-runtime]).
    ///
    /// See [module level][mod] documentation for more details.
    ///
    /// [mod]: index.html
    /// [running-runtime]: index.html#driving-the-runtime
    ///
    /// # Examples
    ///
    /// ```
    /// # #[cfg(not(target_family = "wasm"))]
    /// # {
    /// use tokio::runtime::Runtime;
    ///
    /// # fn dox() {
    /// // Create the runtime
    /// let rt = Runtime::new().unwrap();
    /// // Get a handle from this runtime
    /// let handle = rt.handle();
    ///
    /// // Spawn a future onto the runtime using the handle
    /// handle.spawn(async {
    ///     println!("now running on a worker thread");
    /// });
    /// # }