I'm trying to use Future.rs to manage some tasks in a separate process. I see how to wait for each created future and how to process them one after the other, but I wasn't able to poll the future during its execution to know its state. I always have the error:
thread 'main' panicked at 'no Task is currently running'
I want to do something during the future processing until it finishes. Perhaps I'm not using it the right way? I managed to make it work by using a channel, but I think it should be possible to poll the future and when it's ready get the result. The code I use to test it is:
fn main() {
println!("test future");
let thread_pool = CpuPool::new(4);
let mut future_execution_list = vec![];
let mutex = Arc::new(AtomicUsize::new(0));
//create the future to process
for _ in 0..10 {
let send_mutex = mutex.clone();
let future = thread_pool.spawn_fn(move || {
//Simulate long processing
thread::sleep(time::Duration::from_millis(10));
let num = send_mutex.load(Ordering::Relaxed);
send_mutex.store(num + 1, Ordering::Relaxed);
let res: Result<usize, ()> = Ok(num);
res
});
future_execution_list.push(future);
}
// do the job
loop {
for future in &mut future_execution_list {
match future.poll() {
Ok(Async::NotReady) => (), //do nothing
Ok(Async::Ready(num)) => {
//update task status
println!(" future {:?}", num);
}
Err(_) => {
//log error and set task status to err
()
}
};
}
//do something else
}
}
So I complete my question after Shepmaster answer. Your remarks are very interesting but I still can't find a solutin to my problem. I'll add some informations about my problem. I want to schedule tasks on a automate that can manage several tasks at a time. There is a loop where event are managed and tasks scheduling is calculated. When a task is scheduled, it's spawn. When a task ends a new scheduling is done. During task execution, event are managed. A speudo code can be:
loop {
event.try_recv() { ...} //manage user command for exemple
if (schedule) {
let tasks_to_spawn = schedule_task();
let futures = tasks_to_spawn.map(|task| {
thread_pool.spawn_fn( ....)});
let mut one = future::select_all(futures);
while let Ok((value, _idx, remaining)) = one.wait() {..} //wait here
}
//depend on task end state and event set schedule to true or false.
}
I can joint the scheduling and the task in a future like :
let future = schedule.and_them(|task| execute_task);
But I still need to wait the end of the execution of the first task. I can put everything in a future (event management, schedule, task) and wait the first one that end like you propose. I try but I didn't see how to make a vec of future with different Item and Error type. And with this conception I have to manage more data between thread. Event management and scheduling doesn't have to be executed in a different thread.
I see another problem, select_all take the ownership of the vec. If a new task has to be sheduled during the execution of the other how can I change the vec and add the new future?
Don't know if you have a simple solution. I was thinking that it was simple to get the state of the future during its execution with a method like isDone() without to wait. Perhaps it's planned, I didn't see a PR about that. If you have a simple solution it would be great otherwise I'll rethink my conception.