Spec-Zone.ru › Tokio

Структура Handle

pub struct Handle { /* private fields */ }
Доступно только при включённой возможности crate rt.

Дескриптор среды выполнения.

Дескриптор внутри реализован с подсчётом ссылок, поэтому его можно свободно клонировать. Дескриптор можно получить с помощью метода Runtime::handle.

Реализации

impl Handle

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

Входит в контекст среды выполнения. Это позволяет создавать типы, которым при создании необходим доступный исполнитель, например Sleep или TcpStream. Также это позволит вызывать такие методы, как tokio::spawn и Handle::current, не вызывая паники.

Паники

При многократном вызове Handle::enter возвращённые охранные объекты должны удаляться в обратном порядке относительно порядка их получения. Несоблюдение этого требования приведёт к панике и возможным утечкам памяти.

Примеры
use tokio::runtime::Runtime;

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

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

Не делайте следующего: этот пример демонстрирует ситуацию, которая приведёт к панике и возможной утечке памяти.

ⓘ
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);

pub fn current() -> Self

Возвращает представление Handle текущей работающей Runtime.

Паники

Этот вызов приведёт к панике, если выполняется вне контекста среды выполнения Tokio. Это означает, что вы должны вызвать его в одном из потоков, выполняемых средой выполнения, или из потока с активным EnterGuard. Вызов из потока, созданного, например, с помощью std::thread::spawn, приведёт к панике, если в этом потоке нет активного EnterGuard.

Примеры

Это можно использовать для получения дескриптора окружающей среды выполнения из асинхронного блока или функции, выполняющейся в этой среде.

use tokio::runtime::Handle;

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

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();
});

pub fn try_current() -> Result<Self, TryCurrentError>

Возвращает представление Handle текущей работающей Runtime.

Возвращает ошибку, если Runtime не была запущена.

В отличие от current, этот вызов никогда не приводит к панике.

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

Запускает future в среде выполнения Tokio.

Переданный future запускается в исполнителе среды выполнения, обычно в пуле потоков. Затем пул потоков отвечает за опрос future до его завершения.

Переданный future немедленно начинает выполняться в фоновом режиме при вызове spawn, даже если вы не ожидаете завершения возвращённого JoinHandle (при условии, что среда выполнения работает).

Подробнее см. в документации на уровне модуля.

Примеры
use tokio::runtime::Runtime;

// 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");
});

pub fn spawn_blocking<F, R>(&self, func: F) -> JoinHandle<R> ⓘ
where F: FnOnce() -> R + Send + 'static, R: Send + 'static,

Запускает переданную функцию в исполнителе, предназначенном для блокирующих операций.

Примеры
use tokio::runtime::Runtime;

// 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");
});

pub fn block_on<F: Future>(&self, future: F) -> F::Output

Запускает future до завершения в связанной Runtime этой Handle.

Указанная future выполняется в текущем потоке: выполнение блокируется до её завершения, после чего возвращается полученный результат. Все задачи и таймеры, создаваемые future, будут выполняться в среде выполнения.

При использовании этого метода в среде выполнения current_thread только метод Runtime::block_on может управлять драйверами ввода-вывода и таймеров, а метод Handle::block_on — нет. Это означает, что при использовании этого метода в среде выполнения current_thread всё, что зависит от ввода-вывода или таймеров, не будет работать, если в другом потоке одновременно не вызывается Runtime::block_on для той же среды выполнения.

Если работа среды выполнения была остановлена

Если связанная Runtime этой Handle была остановлена (с помощью Runtime::shutdown_background, Runtime::shutdown_timeout или при её удалении), использование Handle::block_on может привести к ошибке или панике. В частности, ресурсы ввода-вывода вернут ошибку, а таймеры вызовут панику. Future, не зависящие от среды выполнения, продолжат выполняться как обычно.

Паники

Эта функция вызовет панику при выполнении любого из следующих условий:

  • Предоставленная future вызывает панику.
  • Функция вызывается из асинхронного контекста, например внутри Runtime::block_on, Handle::block_on или из функции, помеченной атрибутом tokio::main.
  • Future таймера выполняется в остановленной среде выполнения.
Примеры
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");
});

Или с использованием Handle::current:

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 можно использовать вместе с task::block_in_place, чтобы повторно войти в асинхронный контекст среды выполнения с многопоточным планировщиком:

use tokio::task;
use tokio::runtime::Handle;

task::block_in_place(move || {
    Handle::current().block_on(async move {
        // do something async
    });
});

pub fn runtime_flavor(&self) -> RuntimeFlavor

Возвращает тип текущей среды выполнения Runtime.

Примеры
use tokio::runtime::{Handle, RuntimeFlavor};

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

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

pub fn id(&self) -> Id

Возвращает Id текущей среды выполнения Runtime.

Примеры
use tokio::runtime::Handle;

#[tokio::main(flavor = "current_thread")]
async fn main() {
  println!("Current runtime id: {}", Handle::current().id());
}

pub fn name(&self) -> Option<&str>

Возвращает имя текущей среды выполнения Runtime.

Примеры
use tokio::runtime::Handle;

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

pub fn metrics(&self) -> RuntimeMetrics

Возвращает представление, позволяющее получить сведения о производительности среды выполнения.

impl Handle

pub async fn dump(&self) -> Dump

Доступно только на tokio_unstable и Linux, при включённой возможности crate taskdump и на платформах (AArch64, s390x, x86 или x86-64).

Создаёт снимок состояния среды выполнения.

Если нужно создать снимок состояния только одного future, можно использовать Trace::capture.

Эта функциональность является экспериментальной и имеет ряд требований и ограничений.

Примеры

Это можно использовать для получения трасс вызовов каждой задачи в среде выполнения. Вызовы Handle::dump обычно следует оборачивать в тайм-аут, чтобы создание дампа не превратило блокировку одного потока среды выполнения в блокировку всей среды выполнения.

use tokio::runtime::Handle;
use tokio::time::{timeout, Duration};

// Inside an async block or function.
let handle = Handle::current();
if let Ok(dump) = timeout(Duration::from_secs(2), handle.dump()).await {
    for (i, task) in dump.tasks().iter().enumerate() {
        let trace = task.trace();
        println!("TASK {i}:");
        println!("{trace}\n");
    }
}

В результате получаются подробные трассы задач, например:

TASK 0:
╼ dump::main::{{closure}}::a::{{closure}} at /tokio/examples/dump.rs:18:20
└╼ dump::main::{{closure}}::b::{{closure}} at /tokio/examples/dump.rs:23:20
   └╼ dump::main::{{closure}}::c::{{closure}} at /tokio/examples/dump.rs:28:24
      └╼ tokio::sync::barrier::Barrier::wait::{{closure}} at /tokio/tokio/src/sync/barrier.rs:129:10
         └╼ <tokio::util::trace::InstrumentedAsyncOp<F> as core::future::future::Future>::poll at /tokio/tokio/src/util/trace.rs:77:46
            └╼ tokio::sync::barrier::Barrier::wait_internal::{{closure}} at /tokio/tokio/src/sync/barrier.rs:183:36
               └╼ tokio::sync::watch::Receiver<T>::changed::{{closure}} at /tokio/tokio/src/sync/watch.rs:604:55
                  └╼ tokio::sync::watch::changed_impl::{{closure}} at /tokio/tokio/src/sync/watch.rs:755:18
                     └╼ <tokio::sync::notify::Notified as core::future::future::Future>::poll at /tokio/tokio/src/sync/notify.rs:1103:9
                        └╼ tokio::sync::notify::Notified::poll_notified at /tokio/tokio/src/sync/notify.rs:996:32
Требования
Отладочная информация должна быть доступна

Для создания трасс задач приложение не должно компилироваться с split debuginfo. В Linux включение debuginfo в двоичный файл приложения является (правильным) поведением по умолчанию. Дополнительно обеспечить это поведение можно с помощью следующей директивы в Cargo.toml:

[profile.*]
split-debuginfo = "off"
Нестабильные возможности

Эта функциональность нестабильна и требует включения как --cfg tokio_unstable, так и возможности Cargo taskdump.

Для этого задайте переменную окружения RUSTFLAGS перед вызовом cargo; например:

RUSTFLAGS="--cfg tokio_unstable" cargo run --example dump

Или настройте rustflags в .cargo/config.toml:

[build]
rustflags = ["--cfg", "tokio_unstable"]
Требования к платформе

Дампы задач поддерживаются в Linux на базе aarch64, x86, x86_64 и s390x.

Требования для среды выполнения с одним потоком

В среде выполнения current_thread запрашивать дампы задач можно только внутри контекста среды выполнения, для которой создаётся дамп. Например, не следует ожидать завершения Handle::dump() в другой среде выполнения.

Ограничения
Производительность

Хотя включение возможности taskdump практически не создаёт дополнительной нагрузки на среду выполнения, вызов Handle::dump требует значительных затрат. Среда выполнения должна синхронизировать и приостановить рабочие потоки, а затем повторно опросить каждую задачу в специальном режиме трассировки. Не запрашивайте дампы слишком часто.

Локальные исполнители

Задачи, которыми управляют локальные исполнители (например, FuturesUnordered и LocalSet), могут не отображаться в дампах задач.

Незавершение работы при блокировке рабочих потоков

Future, созданный с помощью Handle::dump, может никогда не выдать Ready, если другой рабочий поток среды выполнения заблокирован более чем на 250 мс. Такое может произойти, если дамп запрашивается во время завершения работы или если другой рабочий поток среды выполнения бесконечно выполняет цикл либо синхронно заблокирован. Поэтому создание дампов задач обычно следует сочетать с явным тайм-аутом.

Реализации трейтов

impl Clone for Handle

fn clone(&self) -> Handle

Возвращает дубликат значения. Подробнее
1.0.0 (const: unstable) ·

fn clone_from(&mut self, source: &Self)

Выполняет копирующее присваивание из source. Подробнее

impl Debug for Handle

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

Форматирует значение с помощью указанного форматтера. Подробнее

impl RefUnwindSafe for Handle

impl UnwindSafe for Handle

Автоматические реализации трейтов

impl Freeze for Handle

impl Send for Handle

impl Sync for Handle

impl Unpin for Handle

impl UnsafeUnpin for Handle

Обобщённые реализации

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

fn type_id(&self) -> TypeId

Получает TypeId для self. Подробнее

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

fn borrow(&self) -> &T

Неизменяемо заимствует принадлежащее значение. Подробнее

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

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

Изменяемо заимствует принадлежащее значение. Подробнее

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

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

🔬Это экспериментальный API, доступный только в nightly-сборках. (clone_to_uninit)
Выполняет копирующее присваивание из self в dest. Подробнее

impl<T> From<T> for T

fn from(t: T) -> T

Возвращает аргумент без изменений.

impl<T> Instrument for T

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Инструментирует этот тип с помощью переданного Span, возвращая оболочку Instrumented. Подробнее

fn in_current_span(self) -> Instrumented<Self> ⓘ

Инструментирует этот тип с помощью текущего Span, возвращая оболочку Instrumented. Подробнее

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

fn into(self) -> U

Вызывает U::from(self).

То есть это преобразование выполняет то, что выберет реализация From<T> for U.

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

type Owned = T

Тип, получаемый после перехода во владение.

fn to_owned(&self) -> T

Создаёт принадлежащие данные из заимствованных данных, обычно путём клонирования. Подробнее

fn clone_into(&self, target: &mut T)

Использует заимствованные данные для замены принадлежащих данных, обычно путём клонирования. Подробнее

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

type Error = Infallible

Тип, возвращаемый в случае ошибки преобразования.

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Выполняет преобразование.

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

type Error = <U as TryFrom<T>>::Error

Тип, возвращаемый в случае ошибки преобразования.

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

Выполняет преобразование.

impl<T> WithSubscriber for T

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Присоединяет предоставленный Subscriber к этому типу и возвращает обёртку WithDispatch. Подробнее

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Присоединяет текущий по умолчанию Subscriber к этому типу и возвращает обёртку WithDispatch. Подробнее

MIT License
Copyright © Tokio Contributors
https://docs.rs/tokio/1.53.1/tokio/runtime/struct.Handle.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API