1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use crossterm::event::{self, Event};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, mpsc};
use std::thread::JoinHandle;
/// 独立输入线程:持续从 crossterm 读取键盘/鼠标/Resize 事件,放入 channel。
///
/// 主循环只从 `rx` 取事件,无论渲染多慢,输入永远不丢。
/// 编辑器操作时通过 `pause()` / `resume()` 暂停/恢复读取。
pub struct InputThread {
/// 事件接收端(主循环消费)
pub rx: mpsc::Receiver<Event>,
/// 退出标志
quit_flag: Arc<AtomicBool>,
/// 暂停标志(编辑器独占 stdin 时设置)
pause_flag: Arc<AtomicBool>,
/// 后台线程句柄
handle: Option<JoinHandle<()>>,
}
impl InputThread {
/// 启动输入线程,返回 InputThread 实例
pub fn spawn() -> Self {
let (tx, rx) = mpsc::channel::<Event>();
let quit_flag = Arc::new(AtomicBool::new(false));
let pause_flag = Arc::new(AtomicBool::new(false));
let quit = Arc::clone(&quit_flag);
let pause = Arc::clone(&pause_flag);
let handle = std::thread::Builder::new()
.name("input-thread".into())
.spawn(move || {
Self::run_loop(tx, quit, pause);
})
.expect("failed to spawn input thread");
Self {
rx,
quit_flag,
pause_flag,
handle: Some(handle),
}
}
/// 线程内部循环
fn run_loop(tx: mpsc::Sender<Event>, quit: Arc<AtomicBool>, pause: Arc<AtomicBool>) {
while !quit.load(Ordering::Acquire) {
if pause.load(Ordering::Acquire) {
std::thread::sleep(std::time::Duration::from_millis(50));
continue;
}
// poll 50ms:既保证响应退出/暂停信号,又不会忙等
match event::poll(std::time::Duration::from_millis(50)) {
Ok(true) => {
// 二次检查 pause,避免 poll 返回 true 后 pause 已被设置
if pause.load(Ordering::Acquire) {
continue;
}
match event::read() {
Ok(evt) => {
if tx.send(evt).is_err() {
// 主线程已 drop rx,退出
break;
}
}
Err(_) => {
// read 出错(极罕见),短暂休眠后重试
std::thread::sleep(std::time::Duration::from_millis(10));
}
}
}
Ok(false) => {
// poll 超时,无事件,继续循环
}
Err(_) => {
// poll 出错,短暂休眠后重试
std::thread::sleep(std::time::Duration::from_millis(10));
}
}
}
}
/// 暂停输入线程(编辑器需要独占 stdin 时调用)
///
/// 设置 pause_flag 后 sleep 120ms,确保线程退出当前 poll 周期。
/// 使用 Release ordering 保证 store 对其他线程立即可见。
pub fn pause(&self) {
self.pause_flag.store(true, Ordering::Release);
std::thread::sleep(std::time::Duration::from_millis(120));
}
/// 恢复输入线程
pub fn resume(&self) {
self.pause_flag.store(false, Ordering::Release);
}
/// 清空 channel 中的残留事件
pub fn drain(&self) {
while self.rx.try_recv().is_ok() {}
}
/// 停止输入线程并等待其结束
pub fn shutdown(mut self) {
self.stop_inner();
}
/// 内部停止逻辑(shutdown 和 Drop 共用)
fn stop_inner(&mut self) {
self.quit_flag.store(true, Ordering::Release);
if let Some(handle) = self.handle.take() {
let _ = handle.join();
}
}
}
impl Drop for InputThread {
fn drop(&mut self) {
self.stop_inner();
}
}