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
48            .entry(event_type.into())
49            .or_default()
50            .push(Registered { id, f });
51        id
52    }
53
54    /// 注销 HandlerId,无论挂在哪个 type 下;true 表示确实注销了某个。
55    /// 类型列表变空时自动从表中移除该 type(对齐原版 `pop(type)`)。
56    pub fn unregister(&self, id: HandlerId) -> bool {
57        let mut t = self.table.write().unwrap();
58        let mut removed = false;
59        for (_, list) in t.typed.iter_mut() {
60            if let Some(pos) = list.iter().position(|r| r.id == id) {
61                list.remove(pos);
62                removed = true;
63            }
64        }
65        t.typed.retain(|_, l| !l.is_empty());
66        if !removed {
67            let before = t.general.len();
68            t.general.retain(|r| r.id != id);
69            removed = before != t.general.len();
70        }
71        removed
72    }
73
74    /// 注册通用 handler;成功返回 HandlerId。
75    pub fn register_general(&self, f: HandlerFn) -> HandlerId {
76        let id = HandlerId(self.next_id.fetch_add(1, Ordering::Relaxed));
77        self.table
78            .write()
79            .unwrap()
80            .general
81            .push(Registered { id, f });
82        id
83    }
84
85    /// 注销通用 handler。
86    pub fn unregister_general(&self, id: HandlerId) -> bool {
87        let mut t = self.table.write().unwrap();
88        let before = t.general.len();
89        t.general.retain(|r| r.id != id);
90        before != t.general.len()
91    }
92
93    /// 取指定 event_type 的 handler 快照(供分发线程无锁执行)。
94    pub(crate) fn snapshot(&self, event_type: &str) -> Vec<HandlerFn> {
95        let t = self.table.read().unwrap();
96        let mut out = Vec::new();
97        if let Some(list) = t.typed.get(event_type) {
98            out.extend(list.iter().map(|r| r.f.clone()));
99        }
100        out.extend(t.general.iter().map(|r| r.f.clone()));
101        out
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use super::*;
108    use std::sync::atomic::AtomicUsize;
109
110    #[test]
111    fn dispatch_and_unregister() {
112        let reg = HandlerRegistry::default();
113        let cnt = Arc::new(AtomicUsize::new(0));
114        let c1 = cnt.clone();
115        let id1 = reg.register(
116            "eTick.",
117            Arc::new(move |_| {
118                c1.fetch_add(1, Ordering::SeqCst);
119            }),
120        );
121        let c2 = cnt.clone();
122        let id2 = reg.register(
123            "eTick.",
124            Arc::new(move |_| {
125                c2.fetch_add(1, Ordering::SeqCst);
126            }),
127        );
128        // general
129        let c3 = cnt.clone();
130        let g = reg.register_general(Arc::new(move |_| {
131            c3.fetch_add(10, Ordering::SeqCst);
132        }));
133        let snap = reg.snapshot("eTick.");
134        assert_eq!(snap.len(), 3, "2 typed + 1 general");
135        assert_eq!(cnt.load(Ordering::SeqCst), 0);
136
137        // 注销后快照变化
138        assert!(reg.unregister(g));
139        assert!(!reg.unregister(g));
140        let snap = reg.snapshot("eTick.");
141        assert_eq!(snap.len(), 2, "general withdrawn");
142        assert!(reg.unregister(id1));
143        assert!(reg.unregister(id2));
144        // (T2)全部注销后,type 表自动回收:快照为空
145        let snap = reg.snapshot("eTick.");
146        assert!(snap.is_empty(), "empty handler list should be recycled");
147        // 空表回收后重新注册该 type,列表重建、正常可分发
148        let c4 = cnt.clone();
149        let id_re = reg.register(
150            "eTick.",
151            Arc::new(move |_| {
152                c4.fetch_add(1, Ordering::SeqCst);
153            }),
154        );
155        assert_eq!(reg.snapshot("eTick.").len(), 1, "re-register rebuilds list");
156        assert!(reg.unregister(id_re));
157    }
158}