xref: /DragonOS/kernel/src/libs/notifier.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
1 #![allow(dead_code)]
2 use core::fmt::Debug;
3 
4 use crate::libs::{rwlock::RwLock, spinlock::SpinLock};
5 use alloc::{sync::Arc, vec::Vec};
6 use log::warn;
7 use system_error::SystemError;
8 
9 /// @brief 通知链节点
10 pub trait NotifierBlock<V: Clone + Copy, T>: Debug + Send + Sync {
11     /// @brief 通知链中注册的回调函数类型
notifier_call(&self, action: V, data: Option<&T>) -> i3212     fn notifier_call(&self, action: V, data: Option<&T>) -> i32;
13     /// @brief 通知链节点的优先级
priority(&self) -> i3214     fn priority(&self) -> i32;
15 }
16 
17 /// @brief 通知链
18 // TODO: 考虑使用红黑树封装
19 #[derive(Debug)]
20 struct NotifierChain<V: Clone + Copy, T>(Vec<Arc<dyn NotifierBlock<V, T>>>);
21 
22 impl<V: Clone + Copy, T> NotifierChain<V, T> {
new() -> Self23     pub fn new() -> Self {
24         Self(vec![])
25     }
26 
27     /// @brief 将节点注册到通知链
28     /// @param unique_priority 检查通知链中优先级的唯一性
register( &mut self, block: Arc<dyn NotifierBlock<V, T>>, unique_priority: bool, ) -> Result<(), SystemError>29     pub fn register(
30         &mut self,
31         block: Arc<dyn NotifierBlock<V, T>>,
32         unique_priority: bool,
33     ) -> Result<(), SystemError> {
34         let mut index: usize = 0;
35 
36         // 在 notifier chain中寻找第一个优先级比要插入块低的块
37         for b in self.0.iter() {
38             // 判断之前是否已经注册过该节点
39             if Arc::ptr_eq(&block, b) {
40                 warn!(
41                     "notifier callback {:?} already registered",
42                     Arc::as_ptr(&block)
43                 );
44                 return Err(SystemError::EEXIST);
45             }
46 
47             if block.priority() > b.priority() {
48                 break;
49             }
50 
51             // 优先级唯一性检测
52             if block.priority() == b.priority() && unique_priority {
53                 return Err(SystemError::EBUSY);
54             }
55 
56             index += 1;
57         }
58 
59         // 插入 notifier chain
60         self.0.insert(index, block);
61         return Ok(());
62     }
63 
64     /// @brief 在通知链中取消注册节点
unregister(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError>65     pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError> {
66         let remove = self.0.extract_if(|b| Arc::ptr_eq(&block, b));
67         match remove.count() {
68             0 => return Err(SystemError::ENOENT),
69             _ => return Ok(()),
70         }
71     }
72 
73     /// 通知链进行事件通知
74     ///
75     /// ## 参数
76     ///
77     /// - nr_to_call 最大调用回调函数的数量,如果为None,则不限制次数
78     ///
79     /// ## 返回
80     ///
81     /// (最后一次回调函数的返回值,回调次数)
82     ///
83     /// TODO: 增加 NOTIFIER_STOP_MASK 相关功能
call_chain( &self, action: V, data: Option<&T>, nr_to_call: Option<usize>, ) -> (i32, usize)84     pub fn call_chain(
85         &self,
86         action: V,
87         data: Option<&T>,
88         nr_to_call: Option<usize>,
89     ) -> (i32, usize) {
90         let mut ret: i32 = 0;
91         let mut nr_calls: usize = 0;
92 
93         for b in self.0.iter() {
94             if nr_to_call.is_some_and(|x| nr_calls >= x) {
95                 break;
96             }
97             ret = b.notifier_call(action, data);
98             nr_calls += 1;
99         }
100         return (ret, nr_calls);
101     }
102 }
103 
104 /// @brief 原子的通知链,使用 SpinLock 进行同步
105 #[derive(Debug)]
106 pub struct AtomicNotifierChain<V: Clone + Copy, T>(SpinLock<NotifierChain<V, T>>);
107 
108 impl<V: Clone + Copy, T> Default for AtomicNotifierChain<V, T> {
default() -> Self109     fn default() -> Self {
110         Self::new()
111     }
112 }
113 
114 impl<V: Clone + Copy, T> AtomicNotifierChain<V, T> {
new() -> Self115     pub fn new() -> Self {
116         Self(SpinLock::new(NotifierChain::<V, T>::new()))
117     }
118 
register(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError>119     pub fn register(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError> {
120         let mut notifier_chain_guard = self.0.lock();
121         return notifier_chain_guard.register(block, false);
122     }
123 
register_unique_prio( &mut self, block: Arc<dyn NotifierBlock<V, T>>, ) -> Result<(), SystemError>124     pub fn register_unique_prio(
125         &mut self,
126         block: Arc<dyn NotifierBlock<V, T>>,
127     ) -> Result<(), SystemError> {
128         let mut notifier_chain_guard = self.0.lock();
129         return notifier_chain_guard.register(block, true);
130     }
131 
unregister(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError>132     pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError> {
133         let mut notifier_chain_guard = self.0.lock();
134         return notifier_chain_guard.unregister(block);
135     }
136 
call_chain( &self, action: V, data: Option<&T>, nr_to_call: Option<usize>, ) -> (i32, usize)137     pub fn call_chain(
138         &self,
139         action: V,
140         data: Option<&T>,
141         nr_to_call: Option<usize>,
142     ) -> (i32, usize) {
143         let notifier_chain_guard = self.0.lock();
144         return notifier_chain_guard.call_chain(action, data, nr_to_call);
145     }
146 }
147 
148 /// @brief 可阻塞的通知链,使用 RwLock 进行同步
149 // TODO: 使用 semaphore 封装
150 #[derive(Debug)]
151 pub struct BlockingNotifierChain<V: Clone + Copy, T>(RwLock<NotifierChain<V, T>>);
152 
153 impl<V: Clone + Copy, T> BlockingNotifierChain<V, T> {
new() -> Self154     pub fn new() -> Self {
155         Self(RwLock::new(NotifierChain::<V, T>::new()))
156     }
157 
register(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError>158     pub fn register(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError> {
159         let mut notifier_chain_guard = self.0.write();
160         return notifier_chain_guard.register(block, false);
161     }
162 
register_unique_prio( &mut self, block: Arc<dyn NotifierBlock<V, T>>, ) -> Result<(), SystemError>163     pub fn register_unique_prio(
164         &mut self,
165         block: Arc<dyn NotifierBlock<V, T>>,
166     ) -> Result<(), SystemError> {
167         let mut notifier_chain_guard = self.0.write();
168         return notifier_chain_guard.register(block, true);
169     }
170 
unregister(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError>171     pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError> {
172         let mut notifier_chain_guard = self.0.write();
173         return notifier_chain_guard.unregister(block);
174     }
175 
call_chain( &self, action: V, data: Option<&T>, nr_to_call: Option<usize>, ) -> (i32, usize)176     pub fn call_chain(
177         &self,
178         action: V,
179         data: Option<&T>,
180         nr_to_call: Option<usize>,
181     ) -> (i32, usize) {
182         let notifier_chain_guard = self.0.read();
183         return notifier_chain_guard.call_chain(action, data, nr_to_call);
184     }
185 }
186 
187 /// @brief 原始的通知链,由调用者自行考虑同步
188 pub struct RawNotifierChain<V: Clone + Copy, T>(NotifierChain<V, T>);
189 
190 impl<V: Clone + Copy, T> RawNotifierChain<V, T> {
new() -> Self191     pub fn new() -> Self {
192         Self(NotifierChain::<V, T>::new())
193     }
194 
register(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError>195     pub fn register(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError> {
196         return self.0.register(block, false);
197     }
198 
unregister(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError>199     pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError> {
200         return self.0.unregister(block);
201     }
202 
call_chain( &self, action: V, data: Option<&T>, nr_to_call: Option<usize>, ) -> (i32, usize)203     pub fn call_chain(
204         &self,
205         action: V,
206         data: Option<&T>,
207         nr_to_call: Option<usize>,
208     ) -> (i32, usize) {
209         return self.0.call_chain(action, data, nr_to_call);
210     }
211 }
212