Я хотел бы использовать Rust для создания простого планировщика, чтобы запускать несколько одновременных функций в определенное время, но не запускать больше, если они еще не завершены.
Например, если заданный интервал равен одной секунде, планировщик должен запускать функции и не запускать больше, если предыдущие функции не вернулись. Цель состоит в том, чтобы не запускать одну и ту же функцию несколько раз.
Я создал рабочий пример с Go следующим образом:
package main
import (
"fmt"
"sync"
"time"
)
func myFunc(wg *sync.WaitGroup) {
fmt.Printf("now: %+s\n", time.Now())
time.Sleep(3 * time.Second)
wg.Done()
}
func main() {
quit := make(chan bool)
t := time.NewTicker(time.Second)
go func() {
for {
select {
case <-t.C:
var wg sync.WaitGroup
for i := 0; i <= 4; i++ {
wg.Add(1)
go myFunc(&wg)
}
wg.Wait()
fmt.Printf("--- done ---\n\n")
case <-quit:
return
}
}
}()
<-time.After(time.Minute)
close(quit)
}
Поскольку в стандартной библиотеке Rust я не нашел что-то вроде NewTicker
Go, я использовал Tokio и придумали
extern crate futures;
extern crate tokio;
use futures::future::lazy;
use std::{thread, time};
use tokio::prelude::*;
use tokio::timer::Interval;
fn main() {
let task = Interval::new(time::Instant::now(), time::Duration::new(1, 0))
.for_each(|interval| {
println!("Interval: {:?}", interval);
for i in 0..5 {
tokio::spawn(lazy(move || {
println!("I am i: {}", i);
thread::sleep(time::Duration::from_secs(3));
Ok(())
}));
}
Ok(())
})
.map_err(|e| panic!("interval errored; err={:?}", e));
tokio::run(task);
}
Проблема, с которой я сталкиваюсь при таком подходе, состоит в том, что задачи не ждут вызова предыдущих функций, поэтому функции запускаются снова, независимо от того, выполнялись ли они ранее, я здесь упускаю что-то вроде sync.WaitGroup
в Go. Что можно использовать для достижения тех же результатов, что и в рабочем примере?
Можно ли добиться этого, используя только стандартную библиотеку? Это в основном для целей обучения, вероятно, есть довольно простой способ сделать это, и я мог бы избежать дополнительной сложности.
В конце я хотел бы периодически отслеживать некоторые сайты по HTTP (получить только возвращенный код состояния), но не запрашивать их все снова, пока у меня не появятся все ответы.