Из моего понимания (я, наверное, неправильно понимаю идею) я
возвращая Future
в другое будущее
Вы не ошиблись, но в коде, который вы указали, единственным возвращаемым будущим является Ok(())
, который реализует IntoFuture
. tokio::spawn
просто порождает новое задание в DefaultExecutor
Токио.
Если я понимаю из вашего вопроса, вы хотите порождать следующую партию , когда предыдущая одна завершена, но если предыдущая сделана до 1 секунды, вы хотите закончить 1 секунда перед порождением следующей партии.
Лучше было бы реализовать собственное будущее и самостоятельно провести опрос, но это можно сделать примерно так:
- Используя
join_all
для сбора пакетных заданий. Это новое будущее, которое ожидает завершения собранных фьючерсов.
- Для ожидания 1 секунды вы можете использовать атомарное состояние. Если он заблокирован для галочки, он ожидает освобождения состояния.
Вот код ( Детская площадка ):
extern crate futures;
extern crate tokio;
use futures::future::lazy;
use std::time::{self, Duration, Instant};
use tokio::prelude::*;
use tokio::timer::{Delay, Interval};
use futures::future::join_all;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
fn main() {
let locker = Arc::new(AtomicBool::new(false));
let task = Interval::new(time::Instant::now(), time::Duration::new(1, 0))
.map_err(|e| panic!("interval errored; err={:?}", e))
.for_each(move |interval| {
let is_locked = locker.load(Ordering::SeqCst);
println!("Interval: {:?} --- {:?}", interval, is_locked);
if !is_locked {
locker.store(true, Ordering::SeqCst);
println!("locked");
let futures: Vec<_> = (0..5)
.map(|i| {
lazy(move || {
println!("Running Task-{}", i);
// mock delay
Delay::new(Instant::now() + Duration::from_millis(100 - i))
.then(|_| Ok(()))
})
.and_then(move |_| {
println!("Task-{} is done", i);
Ok(())
})
})
.collect();
let unlocker = locker.clone();
tokio::spawn(join_all(futures).and_then(move |_| {
unlocker.store(false, Ordering::SeqCst);
println!("unlocked");
Ok(())
}));
}
Ok(())
});
tokio::run(task.then(|_| Ok(())));
}
Выход:
Interval: Instant { tv_sec: 4036783, tv_nsec: 211837425 } --- false
locked
Running Task-0
Running Task-1
Running Task-2
Running Task-3
Running Task-4
Task-4 is done
Task-3 is done
Task-2 is done
Task-1 is done
Task-0 is done
unlocked
Interval: Instant { tv_sec: 4036784, tv_nsec: 211837425 } --- false
locked
Running Task-0
Running Task-1
Running Task-2
Running Task-3
Running Task-4
Task-3 is done
Task-4 is done
Task-0 is done
Task-1 is done
Task-2 is done
unlocked
Внимание! : Пожалуйста, проверьте Комментарий Шепмастера
Даже для демонстрации, вы не должны использовать thread: sleep в фьючерсах.
Есть лучшие альтернативы