优化停止逻辑

This commit is contained in:
lbl8603
2024-06-27 22:09:25 +08:00
parent 54b1fef164
commit 31f0213fc5
3 changed files with 97 additions and 13 deletions
+39 -4
View File
@@ -1,5 +1,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use std::ops::Deref;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
@@ -33,6 +34,32 @@ use crate::{nat, VntCallback};
#[derive(Clone)] #[derive(Clone)]
pub struct Vnt { pub struct Vnt {
inner: Arc<VntInner>,
}
impl Vnt {
#[cfg(feature = "integrated_tun")]
pub fn new<Call: VntCallback>(config: Config, callback: Call) -> anyhow::Result<Self> {
let inner = Arc::new(VntInner::new(config, callback)?);
Ok(Self { inner })
}
#[cfg(not(feature = "integrated_tun"))]
pub fn new_device<Call: VntCallback, Device: DeviceWrite>(
config: Config,
callback: Call,
device: Device,
) -> anyhow::Result<Self> {
let inner = Arc::new(VntInner::new_device(config, callback, device)?);
Ok(Self { inner })
}
}
impl Deref for Vnt {
type Target = VntInner;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
pub struct VntInner {
stop_manager: StopManager, stop_manager: StopManager,
config: Config, config: Config,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
@@ -48,10 +75,10 @@ pub struct Vnt {
external_route: ExternalRoute, external_route: ExternalRoute,
} }
impl Vnt { impl VntInner {
#[cfg(feature = "integrated_tun")] #[cfg(feature = "integrated_tun")]
pub fn new<Call: VntCallback>(config: Config, callback: Call) -> anyhow::Result<Self> { pub fn new<Call: VntCallback>(config: Config, callback: Call) -> anyhow::Result<Self> {
Vnt::new_device0(config, callback, DeviceAdapter::default()) VntInner::new_device0(config, callback, DeviceAdapter::default())
} }
#[cfg(not(feature = "integrated_tun"))] #[cfg(not(feature = "integrated_tun"))]
pub fn new_device<Call: VntCallback, Device: DeviceWrite>( pub fn new_device<Call: VntCallback, Device: DeviceWrite>(
@@ -59,7 +86,7 @@ impl Vnt {
callback: Call, callback: Call,
device: Device, device: Device,
) -> anyhow::Result<Self> { ) -> anyhow::Result<Self> {
Vnt::new_device0(config, callback, device) VntInner::new_device0(config, callback, device)
} }
fn new_device0<Call: VntCallback, Device: DeviceWrite>( fn new_device0<Call: VntCallback, Device: DeviceWrite>(
config: Config, config: Config,
@@ -384,7 +411,7 @@ pub fn start<Call: VntCallback>(
) )
} }
impl Vnt { impl VntInner {
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
&self.config.name &self.config.name
} }
@@ -449,6 +476,9 @@ impl Vnt {
let _ = self.context.lock().take(); let _ = self.context.lock().take();
self.stop_manager.stop() self.stop_manager.stop()
} }
pub fn is_stopped(&self) -> bool {
self.stop_manager.is_stopped()
}
pub fn add_stop_listener<F>(&self, name: String, f: F) -> anyhow::Result<crate::util::Worker> pub fn add_stop_listener<F>(&self, name: String, f: F) -> anyhow::Result<crate::util::Worker>
where where
F: FnOnce() + Send + 'static, F: FnOnce() + Send + 'static,
@@ -478,3 +508,8 @@ impl Vnt {
} }
} }
} }
impl Drop for VntInner {
fn drop(&mut self) {
self.stop();
}
}
+6 -2
View File
@@ -36,8 +36,8 @@ impl StopManager {
pub fn wait_timeout(&self, dur: Duration) -> bool { pub fn wait_timeout(&self, dur: Duration) -> bool {
self.inner.wait_timeout(dur) self.inner.wait_timeout(dur)
} }
pub fn is_stop(&self) -> bool { pub fn is_stopped(&self) -> bool {
self.inner.state.load(Ordering::Acquire) self.inner.is_stopped()
} }
} }
@@ -89,6 +89,9 @@ impl StopManagerInner {
listener(); listener();
} }
} }
pub fn is_stopped(&self) -> bool {
self.worker_num.load(Ordering::Acquire) == 0
}
fn wait(&self) { fn wait(&self) {
{ {
let mut guard = self.park_threads.lock(); let mut guard = self.park_threads.lock();
@@ -115,6 +118,7 @@ impl StopManagerInner {
self.worker_num.load(Ordering::Acquire) == 0 self.worker_num.load(Ordering::Acquire) == 0
} }
fn stop_call(&self) { fn stop_call(&self) {
self.stop();
if let Some(call) = self.stop_call.lock().take() { if let Some(call) = self.stop_call.lock().take() {
call(); call();
} }
+52 -7
View File
@@ -1,5 +1,8 @@
use crate::util::StopManager; use crate::util::StopManager;
use crossbeam_utils::atomic::AtomicCell;
use std::collections::BinaryHeap; use std::collections::BinaryHeap;
use std::sync::mpsc::TrySendError;
use std::sync::Arc;
use std::{ use std::{
cmp::Ordering, cmp::Ordering,
sync::mpsc::{sync_channel, Receiver, SyncSender}, sync::mpsc::{sync_channel, Receiver, SyncSender},
@@ -10,45 +13,62 @@ struct DelayedTask {
f: Box<dyn FnOnce(&Scheduler) + Send>, f: Box<dyn FnOnce(&Scheduler) + Send>,
next: Instant, next: Instant,
} }
impl Eq for DelayedTask {} impl Eq for DelayedTask {}
impl PartialEq for DelayedTask { impl PartialEq for DelayedTask {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.next.eq(&other.next) self.next.eq(&other.next)
} }
} }
impl PartialOrd for DelayedTask { impl PartialOrd for DelayedTask {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.next.partial_cmp(&other.next).map(|ord| ord.reverse()) self.next.partial_cmp(&other.next).map(|ord| ord.reverse())
} }
} }
impl Ord for DelayedTask { impl Ord for DelayedTask {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
self.next.cmp(&other.next).reverse() self.next.cmp(&other.next).reverse()
} }
} }
enum Op { enum Op {
Task(DelayedTask), Task(DelayedTask),
Stop, Stop,
} }
#[derive(Clone)] #[derive(Clone)]
pub struct Scheduler { pub struct Scheduler {
sender: SyncSender<Op>, sender: SyncSender<Op>,
state: Arc<AtomicCell<SchedulerState>>,
} }
#[derive(Copy, Clone, Eq, PartialEq)]
enum SchedulerState {
Running,
ShutdownNow, // 立即停止任务执行,队列中剩余的任务不再执行
_Shutdown, //执行完队列中剩余的任务再停止
}
impl Scheduler { impl Scheduler {
pub fn new(stop_manager: StopManager) -> anyhow::Result<Self> { pub fn new(stop_manager: StopManager) -> anyhow::Result<Self> {
let (sender, receiver) = sync_channel::<Op>(32); let (sender, receiver) = sync_channel::<Op>(32);
let s = Self { sender }; let state = Arc::new(AtomicCell::new(SchedulerState::Running));
let s = Self { sender, state };
let s_inner = s.clone(); let s_inner = s.clone();
let worker = { let worker = {
let scheduler = s.clone(); let scheduler = s.clone();
stop_manager.add_listener("Scheduler".into(), move || { stop_manager.add_listener("Scheduler".into(), move || {
scheduler.shutdown(); scheduler.shutdown_now();
})? })?
}; };
std::thread::Builder::new() std::thread::Builder::new()
.name("Scheduler".into()) .name("Scheduler".into())
.spawn(move || { .spawn(move || {
run(receiver, s_inner); run(receiver, &s_inner);
s_inner.shutdown_now();
worker.stop_all(); worker.stop_all();
}) })
.expect("Scheduler"); .expect("Scheduler");
@@ -58,20 +78,44 @@ impl Scheduler {
where where
F: FnOnce(&Scheduler) + Send + 'static, F: FnOnce(&Scheduler) + Send + 'static,
{ {
if self.state.load() != SchedulerState::Running {
log::error!("定时任务执行停止");
return false;
}
let task = DelayedTask { let task = DelayedTask {
f: Box::new(f), f: Box::new(f),
next: Instant::now().checked_add(time).unwrap(), next: Instant::now().checked_add(time).unwrap(),
}; };
self.sender.send(Op::Task(task)).is_ok() // 如果是任务中调用此方法,那这里用send可能会导致整个定时任务阻塞
// 任务总数不能大于或等于通道长度,所以改成try_send快速失败
match self.sender.try_send(Op::Task(task)) {
Ok(_) => true,
Err(e) => {
match e {
TrySendError::Full(_) => {
log::error!("定时任务队列达到上限");
}
TrySendError::Disconnected(_) => {
log::error!("定时任务执行停止 通道关闭");
}
}
false
}
}
} }
pub fn shutdown(self) { pub fn shutdown_now(&self) {
self.state.store(SchedulerState::ShutdownNow);
let _ = self.sender.send(Op::Stop); let _ = self.sender.send(Op::Stop);
} }
} }
fn run(receiver: Receiver<Op>, s_inner: Scheduler) {
fn run(receiver: Receiver<Op>, s_inner: &Scheduler) {
let mut binary_heap = BinaryHeap::<DelayedTask>::with_capacity(32); let mut binary_heap = BinaryHeap::<DelayedTask>::with_capacity(32);
loop { loop {
while let Some(task) = binary_heap.peek() { while let Some(task) = binary_heap.peek() {
if s_inner.state.load() == SchedulerState::ShutdownNow {
return;
}
let now = Instant::now(); let now = Instant::now();
if now < task.next { if now < task.next {
//需要等待对应时间 //需要等待对应时间
@@ -89,7 +133,7 @@ fn run(receiver: Receiver<Op>, s_inner: Scheduler) {
} }
} else { } else {
if let Some(task) = binary_heap.pop() { if let Some(task) = binary_heap.pop() {
(task.f)(&s_inner); (task.f)(s_inner);
} }
} }
} }
@@ -120,6 +164,7 @@ fn run(receiver: Receiver<Op>, s_inner: Scheduler) {
} }
} }
} }
fn add_task(op: Op, binary_heap: &mut BinaryHeap<DelayedTask>) -> bool { fn add_task(op: Op, binary_heap: &mut BinaryHeap<DelayedTask>) -> bool {
return match op { return match op {
Op::Task(task) => { Op::Task(task) => {