Struct Handle

pub struct Handle { /* private fields */ }

Handle to the runtime.

The handle is internally reference-counted and can be freely cloned. A handle can be obtained using the Runtime::handle method.

Implementations

impl Handle

fn enter(&self) -> EnterGuard<'_>

Enters the runtime context. This allows you to construct types that must have an executor available on creation such as Sleep or TcpStream. It will also allow you to call methods such as tokio::spawn and Handle::current without panicking.

Panics

When calling Handle::enter multiple times, the returned guards must be dropped in the reverse order that they were acquired. Failure to do so will result in a panic and possible memory leaks.

Examples

# #[cfg(not(target_family = "wasm"))]
# {
use tokio::runtime::Runtime;

let rt = Runtime::new().unwrap();

let _guard = rt.enter();
tokio::spawn(async {
    println!("Hello world!");
});
# }

Do not do the following, this shows a scenario that will result in a panic and possible memory leak.

use tokio::runtime::Runtime;

let rt1 = Runtime::new().unwrap();
let rt2 = Runtime::new().unwrap();

let enter1 = rt1.enter();
let enter2 = rt2.enter();

drop(enter1);
drop(enter2);
fn current() -> Self

Returns a Handle view over the currently running Runtime.

Panics

This will panic if called outside the context of a Tokio runtime. That means that you must call this on one of the threads being run by the runtime, or from a thread with an active EnterGuard. Calling this from within a thread created by std::thread::spawn (for example) will cause a panic unless that thread has an active EnterGuard.

Examples

This can be used to obtain the handle of the surrounding runtime from an async block or function running on that runtime.

# #[cfg(not(target_family = "wasm"))]
# {
# use std::thread;
# use tokio::runtime::Runtime;
# fn dox() {
# let rt = Runtime::new().unwrap();
# rt.spawn(async {
use tokio::runtime::Handle;

// Inside an async block or function.
let handle = Handle::current();
handle.spawn(async {
    println!("now running in the existing Runtime");
});

# let handle =
thread::spawn(move || {
    // Notice that the handle is created outside of this thread and then moved in
    handle.spawn(async { /* ... */ });
    // This next line would cause a panic because we haven't entered the runtime
    // and created an EnterGuard
    // let handle2 = Handle::current(); // panic
    // So we create a guard here with Handle::enter();
    let _guard = handle.enter();
    // Now we can call Handle::current();
    let handle2 = Handle::current();
});
# handle.join().unwrap();
# });
# }
# }
fn try_current() -> Result<Self, TryCurrentError>

Returns a Handle view over the currently running Runtime

Returns an error if no Runtime has been started

Contrary to current, this never panics

fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
where
    F: Future + Send + 'static,
    F::Output: Send + 'static,

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).

See module level documentation for more details.

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");
});
# }
# }
fn spawn_blocking<F, R>(&self, func: F) -> JoinHandle<R>
where
    F: FnOnce() -> R + Send + 'static,
    R: Send + 'static,

Runs the provided function on an executor dedicated to blocking operations.

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 blocking function onto the runtime using the handle
handle.spawn_blocking(|| {
    println!("now running on a worker thread");
});
# }
# }
fn block_on<F: Future>(&self, future: F) -> F::Output

Runs a future to completion on this Handle's associated Runtime.

This runs the given future on the current thread, blocking until it is complete, and yielding its resolved result. Any tasks or timers which the future spawns internally will be executed on the runtime.

When this is used on a current_thread runtime, only the Runtime::block_on method can drive the IO and timer drivers, but the Handle::block_on method cannot drive them. This means that, when using this method on a current_thread runtime, anything that relies on IO or timers will not work unless there is another thread currently calling Runtime::block_on on the same runtime.

If the runtime has been shut down

If the Handle's associated Runtime has been shut down (through Runtime::shutdown_background, Runtime::shutdown_timeout, or by dropping it) and Handle::block_on is used it might return an error or panic. Specifically IO resources will return an error and timers will panic. Runtime independent futures will run as normal.

Panics

This function will panic if any of the following conditions are met:

  • The provided future panics.
  • It is called from within an asynchronous context, such as inside Runtime::block_on, Handle::block_on, or from a function annotated with tokio::main.
  • A timer future is executed on a runtime that has been shut down.

Examples

# #[cfg(not(target_family = "wasm"))]
# {
use tokio::runtime::Runtime;

// Create the runtime
let rt  = Runtime::new().unwrap();

// Get a handle from this runtime
let handle = rt.handle();

// Execute the future, blocking the current thread until completion
handle.block_on(async {
    println!("hello");
});
# }

Or using Handle::current:

# #[cfg(not(target_family = "wasm"))]
# {
use tokio::runtime::Handle;

#[tokio::main]
async fn main () {
    let handle = Handle::current();
    std::thread::spawn(move || {
        // Using Handle::block_on to run async code in the new thread.
        handle.block_on(async {
            println!("hello");
        });
    });
}
# }

Handle::block_on may be combined with task::block_in_place to re-enter the async context of a multi-thread scheduler runtime:

# #[cfg(not(target_family = "wasm"))]
# {
use tokio::task;
use tokio::runtime::Handle;

# async fn docs() {
task::block_in_place(move || {
    Handle::current().block_on(async move {
        // do something async
    });
});
# }
# }
fn runtime_flavor(&self) -> RuntimeFlavor

Returns the flavor of the current Runtime.

Examples

use tokio::runtime::{Handle, RuntimeFlavor};

#[tokio::main(flavor = "current_thread")]
async fn main() {
  assert_eq!(RuntimeFlavor::CurrentThread, Handle::current().runtime_flavor());
}
# #[cfg(not(target_family = "wasm"))]
# {
use tokio::runtime::{Handle, RuntimeFlavor};

#[tokio::main(flavor = "multi_thread", worker_threads = 4)]
async fn main() {
  assert_eq!(RuntimeFlavor::MultiThread, Handle::current().runtime_flavor());
}
# }
fn id(&self) -> Id

Returns the Id of the current Runtime.

Examples

use tokio::runtime::Handle;

#[tokio::main(flavor = "current_thread")]
async fn main() {
  println!("Current runtime id: {}", Handle::current().id());
}
fn name(&self) -> Option<&str>

Returns the name of the current Runtime.

Examples

use tokio::runtime::Handle;

#[tokio::main(flavor = "current_thread", name = "my-runtime")]
async fn main() {
  println!("Current runtime name: {}", Handle::current().name().unwrap());
}
fn metrics(&self) -> RuntimeMetrics

Returns a view that lets you get information about how the runtime is performing.

Trait Implementations

impl Clone for Handle

fn clone(&self) -> Self

impl Debug for Handle

fn fmt(&self, f: &mut Formatter<'_>) -> Result

impl RefUnwindSafe for Handle

impl UnwindSafe for Handle

Auto Trait Implementations

impl Freeze for Handle

impl Send for Handle

impl Sync for Handle

impl Unpin for Handle

impl UnsafeUnpin for Handle

Blanket Implementations

impl<T> Any for Handle where T: 'static + ?Sized,

fn type_id(&self) -> TypeId

impl<T> Borrow<T> for Handle where T: ?Sized,

fn borrow(&self) -> &T

impl<T> BorrowMut<T> for Handle where T: ?Sized,

fn borrow_mut(&mut self) -> &mut T

impl<T> CloneToUninit for Handle where T: Clone,

unsafe fn clone_to_uninit(&self, dest: *mut u8)

impl<T> From<T> for Handle

fn from(t: T) -> T

Returns the argument unchanged.

impl<T> ToOwned for Handle where T: Clone,

type Owned = T;
fn to_owned(&self) -> T
fn clone_into(&self, target: &mut T)

impl<T, U> Into<U> for Handle where U: From<T>,

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

impl<T, U> TryFrom<U> for Handle where U: Into<T>,

type Error = never;
fn try_from(value: U) -> Result<T, never>

impl<T, U> TryInto<U> for Handle where U: TryFrom<T>,

type Error = <U as TryFrom<T>>::Error;
fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>