1#![allow(unsafe_code)]
97#![forbid(unused_must_use)]
98
99use std::cell::Cell;
100use std::collections::BTreeMap;
101use std::error::Error;
102use std::fmt::{Display, Formatter};
103use std::hash::{Hash, Hasher};
104use std::ops::{Deref, DerefMut};
105use std::sync::{Arc, RwLock, Weak};
106
107pub mod prelude {
108 pub use crate::{Event, EventHandle, EventInvocationError, Invoke};
109}
110
111pub type FnEventHandlerDelegate<TEventArgs> = fn(TEventArgs) -> ();
113
114pub struct Event<TEventArgs = ()> {
116 handlers: Arc<MapLocked<TEventArgs>>,
117}
118
119unsafe impl<TEventArgs: Send + Sync> Sync for Event<TEventArgs> {}
120
121enum HandlerType<TEventArgs> {
123 BoxedFn(Box<dyn Fn(TEventArgs) + Send>),
124 BoxedFnOnce(Cell<Option<Box<dyn FnOnce(TEventArgs) + Send>>>),
125 Function(FnEventHandlerDelegate<TEventArgs>),
126}
127
128unsafe impl<TEventArgs: Send + Sync> Sync for HandlerType<TEventArgs> {}
129
130struct MapLocked<TEventArgs>(RwLock<MapInner<TEventArgs>>);
132
133type MapInner<TEventArgs> = BTreeMap<HandleKey, HandlerType<TEventArgs>>;
135
136#[must_use = "This handle must be held alive for as long as the event should be used."]
139pub struct EventHandle<TEventArgs> {
140 key: HandleKey,
142 pointer: Weak<MapLocked<TEventArgs>>,
144}
145
146#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Copy, Clone)]
148enum HandleKey {
149 PtrOfBox(usize),
150 FunctionPointer(usize),
151}
152
153impl Hash for HandleKey {
155 fn hash<H: Hasher>(&self, state: &mut H) {
156 match self {
157 HandleKey::PtrOfBox(ptr) => {
158 let address = ptr as *const usize as usize;
159 address.hash(state)
160 }
161 HandleKey::FunctionPointer(ptr) => {
162 let address = ptr as *const usize as usize;
163 address.hash(state)
164 }
165 }
166 }
167}
168
169impl<TEventArgs> EventHandle<TEventArgs> {
170 fn new(key: HandleKey, pointer: &Arc<MapLocked<TEventArgs>>) -> Self {
172 Self {
173 key,
174 pointer: Arc::downgrade(pointer),
175 }
176 }
177
178 pub fn is_valid(&self) -> bool {
180 self.pointer.strong_count() > 0
181 }
182
183 pub fn invoke(&self, args: TEventArgs) -> Result<(), EventInvocationError>
188 where
189 TEventArgs: Clone,
190 {
191 if let Some(ptr) = self.pointer.upgrade() {
192 ptr.invoke(args);
193 Ok(())
194 } else {
195 Err(EventInvocationError::EventDropped)
196 }
197 }
198}
199
200#[derive(Debug, PartialEq)]
201pub enum EventInvocationError {
202 EventDropped,
204}
205
206impl Display for EventInvocationError {
207 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
208 match self {
209 EventInvocationError::EventDropped => write!(
210 f,
211 "Event could not be invoked because it was already dropped"
212 ),
213 }
214 }
215}
216
217impl Error for EventInvocationError {}
218
219impl<TEventArgs> Drop for EventHandle<TEventArgs> {
220 fn drop(&mut self) {
221 if let Some(lock) = self.pointer.upgrade() {
222 let mut handlers = lock.write().unwrap();
223 handlers.remove(&self.key);
224 }
225 }
226}
227
228impl<TEventArgs> Event<TEventArgs> {
229 pub fn new() -> Self
230 where
231 TEventArgs: Clone,
232 {
233 Self {
234 handlers: Arc::new(MapLocked::new(MapInner::new())),
235 }
236 }
237
238 pub fn add_fn<T>(&self, handler: T) -> Result<EventHandle<TEventArgs>, String>
239 where
240 T: Fn(TEventArgs) -> () + Send + 'static,
241 {
242 let handler = Box::new(handler);
243 let key = HandleKey::PtrOfBox((&*handler as *const _) as usize);
244 let mut handlers = self.handlers.write().unwrap();
245 let entry = HandlerType::BoxedFn(handler);
246 match handlers.insert(key, entry) {
247 None => Ok(EventHandle::new(key, &self.handlers)),
248 Some(_) => Err(String::from("The handler was already registered")),
249 }
250 }
251
252 pub fn add_fnonce<T>(&self, handler: T) -> Result<EventHandle<TEventArgs>, String>
253 where
254 T: FnOnce(TEventArgs) -> () + Send + 'static,
255 {
256 let handler = Box::new(handler);
257 let key = HandleKey::PtrOfBox((&*handler as *const _) as usize);
258 let mut handlers = self.handlers.write().unwrap();
259 let entry = HandlerType::BoxedFnOnce(Cell::new(Some(handler)));
260 match handlers.insert(key, entry) {
261 None => Ok(EventHandle::new(key, &self.handlers)),
262 Some(_) => Err(String::from("The handler was already registered")),
263 }
264 }
265
266 pub fn add_ptr(
267 &self,
268 handler: FnEventHandlerDelegate<TEventArgs>,
269 ) -> Result<EventHandle<TEventArgs>, String> {
270 let key = HandleKey::FunctionPointer((&handler as *const _) as usize);
271 let mut handlers = self.handlers.write().unwrap();
272 let entry = HandlerType::Function(handler);
273 match handlers.insert(key, entry) {
274 None => Ok(EventHandle::new(key, &self.handlers)),
275 Some(_) => Err(String::from("The handler was already registered")),
276 }
277 }
278
279 pub fn len(&self) -> usize {
281 self.handlers.read().unwrap().len()
282 }
283
284 pub fn invoke(&self, args: TEventArgs)
289 where
290 TEventArgs: Clone,
291 {
292 self.handlers.invoke(args)
293 }
294}
295
296impl Default for Event {
297 fn default() -> Self {
298 Self::new()
299 }
300}
301
302impl<TEventArgs> MapLocked<TEventArgs>
303where
304 TEventArgs: Clone,
305{
306 const fn new(inner: MapInner<TEventArgs>) -> Self {
307 Self(RwLock::new(inner))
308 }
309
310 fn invoke(&self, args: TEventArgs) {
311 let mut unregister_list = Vec::new();
312
313 {
314 let handlers = self.read().unwrap();
315 for (key, entry) in handlers.iter() {
316 let args = args.clone();
317 match &entry {
318 HandlerType::Function(fun) => fun(args),
319 HandlerType::BoxedFn(fun) => fun(args),
320 HandlerType::BoxedFnOnce(cell) => {
321 let fun = cell.replace(None);
322 if fun.is_some() {
323 (fun.unwrap())(args);
324 }
325 unregister_list.push(key.clone());
326 }
327 }
328 }
329 }
330
331 if !unregister_list.is_empty() {
333 let mut handlers = self.write().unwrap();
334 for key in unregister_list {
335 handlers.remove(&key);
336 }
337 }
338 }
339}
340
341impl<TEventArgs> Deref for MapLocked<TEventArgs> {
342 type Target = RwLock<MapInner<TEventArgs>>;
343
344 fn deref(&self) -> &Self::Target {
345 &self.0
346 }
347}
348
349impl<TEventArgs> DerefMut for MapLocked<TEventArgs> {
350 fn deref_mut(&mut self) -> &mut Self::Target {
351 &mut self.0
352 }
353}
354
355pub trait Invoke<TEventArgs>
357where
358 TEventArgs: Clone,
359{
360 fn invoke(&self, args: TEventArgs);
361}
362
363impl<TEventArgs> Invoke<TEventArgs> for Event<TEventArgs>
364where
365 TEventArgs: Clone,
366{
367 fn invoke(&self, args: TEventArgs) {
368 self.invoke(args)
369 }
370}
371
372impl<TEventArgs> Invoke<TEventArgs> for EventHandle<TEventArgs>
373where
374 TEventArgs: Clone,
375{
376 fn invoke(&self, args: TEventArgs) {
377 self.invoke(args).ok();
378 }
379}
380
381#[cfg(test)]
382mod tests {
383 use super::*;
384
385 fn dummy(_args: ()) {
386 println!("Dummy called.");
387 }
388
389 #[test]
390 fn new_handler_has_no_registrations() {
391 let handler = Event::<()>::new();
392 assert_eq!(handler.len(), 0);
393 }
394
395 #[test]
396 #[allow(unused_variables)]
397 fn can_add_fn() {
398 let handler = Event::<()>::new();
399 let handle = handler.add_fn(dummy).unwrap();
400 assert_eq!(handler.len(), 1);
401 handler.invoke(());
402 }
403
404 #[test]
405 #[allow(unused_variables)]
406 fn can_add_fnonce() {
407 let handler = Event::new();
408 let handle = handler.add_fnonce(dummy).unwrap();
409 assert_eq!(handler.len(), 1);
410 handler.invoke(());
411 assert_eq!(handler.len(), 0);
412 }
413
414 #[test]
415 #[allow(unused_variables)]
416 fn can_add_function_pointer() {
417 let handler = Event::<()>::new();
418 let handle = handler.add_ptr(dummy).unwrap();
419 assert_eq!(handler.len(), 1);
420 handler.invoke(());
421 }
422
423 #[test]
424 #[allow(unused_variables)]
425 fn cannot_register_same_function_twice() {
426 let handler = Event::new();
427 let handle = handler.add_ptr(dummy).unwrap();
428 assert!(handler.add_ptr(dummy).is_err());
429 }
430
431 #[test]
432 fn can_remove_handlers() {
433 let handler = Event::new();
434 let handle = handler.add_fn(dummy).unwrap();
435 assert_eq!(handler.len(), 1);
436 drop(handle);
437 assert_eq!(handler.len(), 0);
438 }
439
440 #[test]
441 fn handler_is_sync() {
442 let handler: Event = Event::new();
443 let _sync: Box<dyn Sync> = Box::new(handler);
444 }
445}