Refact. Replace all tokio::time::interval() (#7173)

* Refact. Replace all `tokio::time::interval()`

Signed-off-by: fufesou <shuanglongchen@yeah.net>

* Refact Better min_interval for `ThrottledInterval`.

Signed-off-by: fufesou <shuanglongchen@yeah.net>

---------

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou
2024-02-18 21:18:00 +08:00
committed by GitHub
parent 5fdcc748e1
commit 8c108065eb
9 changed files with 153 additions and 39 deletions

View File

@@ -1,6 +1,7 @@
use std::{
future::Future,
sync::{Arc, Mutex, RwLock},
task::Poll,
};
#[derive(Debug, Eq, PartialEq)]
@@ -132,15 +133,20 @@ use hbb_common::{
bytes::Bytes,
compress::compress as compress_func,
config::{self, Config, CONNECT_TIMEOUT, READ_TIMEOUT},
futures_util::future::poll_fn,
get_version_number, log,
message_proto::*,
protobuf::Enum,
protobuf::Message as _,
protobuf::{Enum, Message as _},
rendezvous_proto::*,
socket_client,
sodiumoxide::crypto::{box_, secretbox, sign},
tcp::FramedStream,
timeout, tokio, ResultType,
timeout,
tokio::{
self,
time::{Duration, Instant, Interval},
},
ResultType,
};
// #[cfg(any(target_os = "android", target_os = "ios", feature = "cli"))]
use hbb_common::{config::RENDEZVOUS_PORT, futures::future::join_all};
@@ -1335,3 +1341,118 @@ pub fn using_public_server() -> bool {
&& crate::get_custom_rendezvous_server(get_option("custom-rendezvous-server")).is_empty()
}
pub struct ThrottledInterval {
interval: Interval,
last_tick: Instant,
min_interval: Duration,
}
impl ThrottledInterval {
pub fn new(i: Interval) -> ThrottledInterval {
let period = i.period();
ThrottledInterval {
interval: i,
last_tick: Instant::now() - period * 2,
min_interval: Duration::from_secs_f64(period.as_secs_f64() * 0.9),
}
}
pub async fn tick(&mut self) -> Instant {
loop {
let instant = poll_fn(|cx| self.poll_tick(cx));
if let Some(instant) = instant.await {
return instant;
}
}
}
pub fn poll_tick(&mut self, cx: &mut std::task::Context<'_>) -> Poll<Option<Instant>> {
match self.interval.poll_tick(cx) {
Poll::Ready(instant) => {
if self.last_tick.elapsed() >= self.min_interval {
self.last_tick = Instant::now();
Poll::Ready(Some(instant))
} else {
// This call is required since tokio 1.27
cx.waker().wake_by_ref();
Poll::Ready(None)
}
}
Poll::Pending => {
Poll::Pending
},
}
}
}
pub type RustDeskInterval = ThrottledInterval;
#[inline]
pub fn rustdesk_interval(i: Interval) -> ThrottledInterval {
ThrottledInterval::new(i)
}
#[cfg(test)]
mod tests {
use super::*;
use chrono::{format::StrftimeItems, Local};
use hbb_common::tokio::{
self,
time::{interval, sleep, Duration},
};
use std::collections::HashSet;
#[tokio::test]
async fn test_tokio_time_interval() {
let mut timer = interval(Duration::from_secs(1));
let mut times = Vec::new();
sleep(Duration::from_secs(3)).await;
loop {
tokio::select! {
_ = timer.tick() => {
let format = StrftimeItems::new("%Y-%m-%d %H:%M:%S");
times.push(Local::now().format_with_items(format).to_string());
if times.len() == 5 {
break;
}
}
}
}
let times2: HashSet<String> = HashSet::from_iter(times.clone());
assert_eq!(times.len(), times2.len() + 3);
}
#[allow(non_snake_case)]
#[tokio::test]
async fn test_RustDesk_interval() {
let mut timer = rustdesk_interval(interval(Duration::from_secs(1)));
let mut times = Vec::new();
sleep(Duration::from_secs(3)).await;
loop {
tokio::select! {
_ = timer.tick() => {
let format = StrftimeItems::new("%Y-%m-%d %H:%M:%S");
times.push(Local::now().format_with_items(format).to_string());
if times.len() == 5 {
break;
}
}
}
}
let times2: HashSet<String> = HashSet::from_iter(times.clone());
assert_eq!(times.len(), times2.len());
}
#[test]
fn test_duration_multiplication() {
let dur = Duration::from_secs(1);
assert_eq!(dur * 2, Duration::from_secs(2));
assert_eq!(Duration::from_secs_f64(dur.as_secs_f64() * 0.9), Duration::from_millis(900));
assert_eq!(Duration::from_secs_f64(dur.as_secs_f64() * 0.923), Duration::from_millis(923));
assert_eq!(Duration::from_secs_f64(dur.as_secs_f64() * 0.923 * 1e-3), Duration::from_micros(923));
assert_eq!(Duration::from_secs_f64(dur.as_secs_f64() * 0.923 * 1e-6), Duration::from_nanos(923));
assert_eq!(Duration::from_secs_f64(dur.as_secs_f64() * 0.923 * 1e-9), Duration::from_nanos(1));
assert_eq!(Duration::from_secs_f64(dur.as_secs_f64() * 0.923 * 1e-10), Duration::from_nanos(0));
}
}