Future это тип, для которого имплементирован трейт Future
Executor. В общем случае, это может быть ивент-луп ( цикл событий, event loop ), тред пул или что-то еще: executor.
Вы же используете tokio? Тогда, на сегодняшний день, вариантов всего два:
многопоточный executor
и
однопоточный executor.
По умолчанию (то есть если вы просто используете tokio::run
и tokio::spawn
используется многопоточный вариант).
0.3 экспериментальная версия, сейчас все используют 0.1. Принципиальных различий между ними нет.
Уже есть в nightly для futures 0.3. Но tokio пока использует futures 0.1. Есть экспериментальная поддержка
Краткое введение: https://tokio.rs/ Немного про то как работает Executor: http://rust-lang-nursery.github.io/futures-rs/blog/2018/08/17/toykio.html ...
https://docs.rs/tokio-fs/0.1.3/tokio_fs/
К сожалению, не существует платформо-независимого способа работать с файлами в неблокирущем режиме, поэтому tokio-fs
использует специальную функцию
blocking
(см. дальше по FAQ) для того, чтобы избежать блокировки ивент-лупа.
https://docs.rs/tokio/0.1.8/tokio/io/fn.stdin.html https://docs.rs/tokio/0.1.8/tokio/io/fn.stdout.html
Использовать blocking.
Этот самый blocking
как бы даёт подсказку tokio, что то, что вы собираетесь запустить — это всерьёз и надолго.
Тут надо отметить, что стандартная практика предписывает, что метод poll
(из трейта
Future
) должен завершаться как можно скорее, пусть и со статусом Async::NotReady
. Очевидно, ваш блокирующий вызов к базе данных может занять.. некоторое время. Именно для таких случаев и была сделана функция
blocking.
Когда tokio получает такую задачу, то он переносит обработку цикла событий (event loop) в другой поток, избегая, таким образом, блокировки вообще всего.
Task это фьюча верхнего уровня. Т.е. то что передается в tokio::run(..) или tokio::spawn(..). Каждый spawn() создает новый таск. Таск подобен треду операционной системы, но является легковесным.
Дефолтный рантайм tokio запускает тред пул. Таски разбирают треды из пула: work stealing.
Все верно, так и должно быть! Вы заблокировали текущий тред и теперь ивент луп не может продолжить работу. Безопасно вызывать .wait() можно только на фьючах, отправленных в тред пул.