Skip to main content

ek_event/
handler.rs

1//! handler 注册表:`RwLock<精确表 + general 表>`,HandlerId 去重。
2//!
3//! 原版差异:
4//! - 原版 `defaultdict(list)` + `list[handler]`(对象相等去重)在 Rust 不可复刻(闭包不可比),
5//!   改为注册时分配自增 [`HandlerId`],上层可保存 id 用于注销。
6//! - 全程 RwLock 保护(原版无锁靠 GIL,这里修正)。
7
8use crate::event::Event;
9use std::collections::HashMap;
10use std::sync::atomic::{AtomicU64, Ordering};
11use std::sync::{Arc, RwLock};
12
13/// handler 函数签名(与原版 `Callable[[Event], None]` 对齐)。
14pub type HandlerFn = Arc<dyn Fn(&Event) + Send + Sync>;
15
16/// 注册标识;unregister 凭它定位。
17#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
18pub struct HandlerId(pub(crate) u64);
19
20struct Registered {
21    id: HandlerId,
22    f: HandlerFn,
23}
24
25#[derive(Default)]
26struct Table {
27    /// event_type -> 按注册顺序的 handler 列表(精确匹配分发)。
28    typed: HashMap<String, Vec<Registered>>,
29    /// 通用 handler 列表(收所有事件,在 type handler 之后执行)。
30    general: Vec<Registered>,
31}
32
33/// handler 注册管理器。线程安全。(含不透明函数对象,不 derive Debug)
34#[derive(Default)]
35pub struct HandlerRegistry {
36    table: RwLock<Table>,
37    next_id: AtomicU64,
38}
39
40impl HandlerRegistry {
41    /// 注册 handler 至指定 event_type,返回全局唯一 [`HandlerId`] 供注销。
42    /// 注意:每次注册都会新增一条(闭包不可比较,原版"函数相等去重"无法复刻);
43    /// 防重复注册由调用方负责,引擎只保证 id 唯一且可精确注销。
44    pub fn register(&self, event_type: impl Into<String>, f: HandlerFn) -> HandlerId {
45        let id = HandlerId(self.next_id.fetch_add(1, Ordering::Relaxed));
46        let mut t = self.table.write().unwrap();
47        t.typed.entry(event_type.into()).or_default().push(Registered { id, f });
48        id
49    }
50
51    /// 注销 HandlerId,无论挂在哪个 type 下;true 表示确实注销了某个。
52    /// 类型列表变空时自动从表中移除该 type(对齐原版 `pop(type)`)。
53    pub fn unregister(&self, id: HandlerId) -> bool {
54        let mut t = self.table.write().unwrap();
55        let mut removed = false;
56        for (_, list) in t.typed.iter_mut() {
57            if let Some(pos) = list.iter().position(|r| r.id == id) {
58                list.remove(pos);
59                removed = true;
60            }
61        }
62        t.typed.retain(|_, l| !l.is_empty());
63        if !removed {
64            let before = t.general.len();
65            t.general.retain(|r| r.id != id);
66            removed = before != t.general.len();
67        }
68        removed
69    }
70
71    /// 注册通用 handler;成功返回 HandlerId。
72    pub fn register_general(&self, f: HandlerFn) -> HandlerId {
73        let id = HandlerId(self.next_id.fetch_add(1, Ordering::Relaxed));
74        self.table.write().unwrap().general.push(Registered { id, f });
75        id
76    }
77
78    /// 注销通用 handler。
79    pub fn unregister_general(&self, id: HandlerId) -> bool {
80        let mut t = self.table.write().unwrap();
81        let before = t.general.len();
82        t.general.retain(|r| r.id != id);
83        before != t.general.len()
84    }
85
86    /// 取指定 event_type 的 handler 快照(供分发线程无锁执行)。
87    pub(crate) fn snapshot(&self, event_type: &str) -> Vec<HandlerFn> {
88        let t = self.table.read().unwrap();
89        let mut out = Vec::new();
90        if let Some(list) = t.typed.get(event_type) {
91            out.extend(list.iter().map(|r| r.f.clone()));
92        }
93        out.extend(t.general.iter().map(|r| r.f.clone()));
94        out
95    }
96}
97
98#[cfg(test)]
99mod tests {
100    use super::*;
101    use std::sync::atomic::AtomicUsize;
102
103    #[test]
104    fn dispatch_and_unregister() {
105        let reg = HandlerRegistry::default();
106        let cnt = Arc::new(AtomicUsize::new(0));
107        let c1 = cnt.clone();
108        let id1 = reg.register("eTick.", Arc::new(move |_| {
109            c1.fetch_add(1, Ordering::SeqCst);
110        }));
111        let c2 = cnt.clone();
112        let id2 = reg.register("eTick.", Arc::new(move |_| {
113            c2.fetch_add(1, Ordering::SeqCst);
114        }));
115        // general
116        let c3 = cnt.clone();
117        let g = reg.register_general(Arc::new(move |_| {
118            c3.fetch_add(10, Ordering::SeqCst);
119        }));
120        let snap = reg.snapshot("eTick.");
121        assert_eq!(snap.len(), 3, "2 typed + 1 general");
122        assert_eq!(cnt.load(Ordering::SeqCst), 0);
123
124        // 注销后快照变化
125        assert!(reg.unregister(g));
126        assert!(!reg.unregister(g));
127        let snap = reg.snapshot("eTick.");
128        assert_eq!(snap.len(), 2, "general withdrawn");
129        assert!(reg.unregister(id1));
130        assert!(reg.unregister(id2));
131        // (T2)全部注销后,type 表自动回收:快照为空
132        let snap = reg.snapshot("eTick.");
133        assert!(snap.is_empty(), "empty handler list should be recycled");
134        // 空表回收后重新注册该 type,列表重建、正常可分发
135        let c4 = cnt.clone();
136        let id_re = reg.register("eTick.", Arc::new(move |_| {
137            c4.fetch_add(1, Ordering::SeqCst);
138        }));
139        assert_eq!(reg.snapshot("eTick.").len(), 1, "re-register rebuilds list");
140        assert!(reg.unregister(id_re));
141    }
142}