No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lib.rs 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. /*
  2. * Event Bus
  3. * Copyright (C) 2018 Soni L.
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. /// Registers an event hook.
  19. ///
  20. /// Usage: `register_hook!(bus, priority, type, handler)`
  21. #[macro_export]
  22. macro_rules! register_hook {
  23. ($b:expr, $p:expr, $t:ty, $h:expr) => {
  24. {
  25. // hygiene
  26. let bus: &$crate::EventBus = $b;
  27. let hook = $h;
  28. let pri = $p;
  29. {
  30. static EVENT_ID: ::std::sync::atomic::AtomicUsize = std::sync::atomic::ATOMIC_USIZE_INIT;
  31. static EVENT_ID_INIT: ::std::sync::Once = std::sync::ONCE_INIT;
  32. // no generics allowed.
  33. static _DUMMY: ::std::marker::PhantomData<dyn Fn(&mut $t) + Send + Sync> = ::std::marker::PhantomData;
  34. EVENT_ID_INIT.call_once(|| {
  35. EVENT_ID.store($crate::get_event_id::<$t>(), std::sync::atomic::Ordering::Relaxed);
  36. });
  37. let id = EVENT_ID.load(std::sync::atomic::Ordering::Relaxed);
  38. $crate::register::<$t, _>(bus, pri, hook, id)
  39. }
  40. }
  41. }
  42. }
  43. /// Posts an event.
  44. ///
  45. /// Usage: `post_event!(bus, event, type, type, ...)`
  46. #[macro_export]
  47. macro_rules! post_event {
  48. // prefer (bus, ty, ty, ty, ..., evt) but rust is just bad at parsing
  49. ($b:expr, $e:expr, $($t:ty),+) => {
  50. {
  51. // hygiene
  52. let bus: &$crate::EventBus = $b;
  53. // event setup, this may evaluate to any type.
  54. let event: &mut _ = $e;
  55. {
  56. // it is a logic error for an event's cancellability to change based on its value.
  57. static CANCELLABLE: ::std::sync::atomic::AtomicBool = ::std::sync::atomic::ATOMIC_BOOL_INIT;
  58. static CANCELLABLE_INIT: ::std::sync::Once = ::std::sync::ONCE_INIT;
  59. CANCELLABLE_INIT.call_once(|| {
  60. CANCELLABLE.store(<$crate::Event>::cancellable(event), std::sync::atomic::Ordering::Relaxed);
  61. });
  62. let cancellable = CANCELLABLE.load(std::sync::atomic::Ordering::Relaxed);
  63. #[allow(unused_mut)]
  64. let mut event_handlers = ::std::iter::empty::<(i32, Box<dyn Fn(&mut _)>)>();
  65. $(
  66. let handlers;
  67. #[allow(unused_mut)]
  68. let mut event_handlers = {
  69. // event type setup
  70. static EVENT_ID: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::ATOMIC_USIZE_INIT;
  71. static EVENT_ID_INIT: ::std::sync::Once = ::std::sync::ONCE_INIT;
  72. // no generics allowed.
  73. static _DUMMY: ::std::marker::PhantomData<dyn Fn(&mut $t) + Send + Sync> = ::std::marker::PhantomData;
  74. EVENT_ID_INIT.call_once(|| {
  75. EVENT_ID.store($crate::get_event_id::<$t>(), std::sync::atomic::Ordering::Relaxed);
  76. });
  77. let id = EVENT_ID.load(std::sync::atomic::Ordering::Relaxed);
  78. // handler retrieval and invokation
  79. {
  80. let subevent: &mut $t = event;
  81. handlers = $crate::get_post_targets::<$t>(bus, subevent, id);
  82. }
  83. $crate::type_hint_trick(event, event_handlers, handlers.iter().cloned(), |f| move |evt| f(evt))
  84. };
  85. )+
  86. for (_pri, fun) in event_handlers {
  87. fun(event);
  88. if cancellable && <_ as $crate::Event>::cancelled(event) {
  89. break;
  90. }
  91. }
  92. cancellable && <_ as $crate::Event>::cancelled(event)
  93. }
  94. }
  95. }
  96. }
  97. /// Basic trait for defining an event.
  98. pub trait Event: 'static {
  99. /// Returns whether this event is cancellable.
  100. ///
  101. /// When this is true, `cancelled` and `cancel` should also be implemented.
  102. ///
  103. /// Note: While this method does take a `&self`, it's a logic error for an event's
  104. /// cancellability to change based on its value. The `&self` is just for trait objectification.
  105. /// You have been warned!
  106. fn cancellable(&self) -> bool {
  107. false
  108. }
  109. /// Returns whether this event has been cancelled.
  110. fn cancelled(&self) -> bool {
  111. false
  112. }
  113. /// Sets whether this event is cancelled.
  114. ///
  115. /// # Panics
  116. ///
  117. /// Panics if this event is not cancellable.
  118. fn set_cancelled(&mut self, cancel: bool) {
  119. let _ = cancel;
  120. panic!("not cancellable");
  121. }
  122. }
  123. /// An event bus.
  124. pub struct EventBus {
  125. id: usize,
  126. dropper: Mutex<LinkedList<Box<dyn Fn(usize) + Send + Sync>>>,
  127. }
  128. #[doc(hidden)]
  129. pub fn type_hint_trick<T: Event + Sized, A, B, C: Event + ?Sized, E>(_event: &mut T, event_handlers: A, handlers: B, convert: fn(::std::sync::Arc<dyn Fn(&mut C) + Send + Sync>) -> E) -> impl ::std::iter::Iterator<Item=(i32, Box<dyn for<'a> Fn(&'a mut T) + 'static>)> where
  130. A: ::std::iter::Iterator<Item=(i32, Box<dyn Fn(&mut T)>)>,
  131. B: ::std::iter::Iterator<Item=(i32, ::std::sync::Arc<dyn Fn(&mut C) + Send + Sync>)>,
  132. E: Fn(&mut T) + 'static,
  133. {
  134. itertools::merge_join_by(event_handlers, handlers, |l, r| l.0.cmp(&r.0))
  135. .map(move |eob: itertools::EitherOrBoth<(i32, Box<dyn Fn(&mut T)>), (i32, ::std::sync::Arc<dyn Fn(&mut C) + Send + Sync>)>| ({
  136. eob.as_ref().left().map(|v| v.0).or_else(|| eob.as_ref().right().map(|v| v.0)).unwrap_or(0)
  137. }, Box::new(move |evt: &mut _| {
  138. eob.as_ref().left().map(|x| (x.1)(evt));
  139. eob.as_ref().right().map(|x| convert(x.1.clone())(evt));
  140. }) as Box<_>))
  141. }
  142. #[macro_use]
  143. extern crate lazy_static;
  144. extern crate anymap;
  145. extern crate itertools;
  146. //use std::marker::PhantomData;
  147. use std::sync::atomic::AtomicUsize;
  148. use std::sync::atomic::ATOMIC_USIZE_INIT;
  149. use std::sync::atomic::Ordering as AtomicOrdering;
  150. use std::sync::Mutex;
  151. use std::collections::LinkedList;
  152. use std::any::Any;
  153. use std::sync::Arc;
  154. use std::sync::RwLock;
  155. use std::mem;
  156. /* only exists as a module to keep us from accidentally misusing these */
  157. mod id_map {
  158. use std::marker::PhantomData;
  159. use std::sync::atomic::AtomicUsize;
  160. use std::sync::atomic::ATOMIC_USIZE_INIT;
  161. use std::sync::atomic::Ordering as AtomicOrdering;
  162. use std::sync::Mutex;
  163. use std::sync::Arc;
  164. use super::Event;
  165. use super::Handlers;
  166. lazy_static! {
  167. static ref EVENT_ID_MAP: Mutex<::anymap::Map<::anymap::any::Any + Send + Sync>> = Mutex::new(::anymap::Map::new());
  168. }
  169. struct EventId<T: Event + ?Sized> {
  170. id: usize,
  171. _t: PhantomData<dyn Fn(&mut T) + Send + Sync>
  172. }
  173. pub fn get_event_id<T: Event + ?Sized>() -> usize {
  174. static EVENT_ID_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
  175. EVENT_ID_MAP.lock().expect("failed to allocate event id").entry::<EventId<T>>().or_insert_with(|| {
  176. let handlers: Arc<Handlers<T>> = Default::default();
  177. Arc::make_mut(&mut super::HANDLERS.write().expect("???")).push(handlers);
  178. EventId { id: EVENT_ID_COUNT.fetch_add(1, AtomicOrdering::SeqCst), _t: PhantomData }
  179. }).id
  180. }
  181. }
  182. /// Low-level event handling function, returns the event ID for use with get_post_targets.
  183. ///
  184. /// This function is (extremely) slow!
  185. pub fn get_event_id<T: Event + ?Sized>() -> usize {
  186. id_map::get_event_id::<T>()
  187. }
  188. type RwArcVec<T> = RwLock<Arc<Vec<T>>>;
  189. struct Handlers<T: Event + ?Sized>(RwArcVec<RwArcVec<(i32, Arc<dyn Fn(&mut T) + Send + Sync>)>>);
  190. impl<T: Event + ?Sized> Default for Handlers<T> {
  191. fn default() -> Self {
  192. Handlers(Default::default())
  193. }
  194. }
  195. lazy_static! {
  196. static ref HANDLERS: RwArcVec<Arc<dyn Any + Send + Sync>> = Default::default();
  197. }
  198. /// Low-level event handling function, returns the handlers that should be called to post the
  199. /// event.
  200. ///
  201. /// This is useful if you want to simulate inheritance.
  202. ///
  203. /// # Panics
  204. ///
  205. /// Panics if `id` doesn't match the given `T` (but not if the given `id` doesn't exist).
  206. pub fn get_post_targets<T: Event + ?Sized>(bus: &EventBus, _event: &mut T, id: usize) -> Arc<Vec<(i32, Arc<dyn Fn(&mut T) + Send + Sync>)>> {
  207. let target: Option<Arc<Vec<_>>> = HANDLERS.read().expect("failed to lock for reading").get(id).map(|arc| Arc::clone(arc))
  208. .map(|any| Arc::downcast::<Handlers<T>>(any).expect("Wrong id"))
  209. .and_then(|handlers| handlers.0.read().expect("failed to lock for reading").get(bus.id).map(|hooks| Arc::clone(&*hooks.read().expect("failed to lock for reading"))));
  210. target.unwrap_or_else(|| Arc::new(Vec::new()))
  211. }
  212. /// Low-level event handling function, registers an event.
  213. ///
  214. /// This function is kinda slow. It doesn't block currently executing hooks (and, in fact, may be
  215. /// safely called from a running hook), but does block threads from starting hook execution.
  216. ///
  217. /// # Panics
  218. ///
  219. /// Panics if `id` doesn't match the given `T`, or if `id` doesn't exist.
  220. pub fn register<T: Event + ?Sized, F: for<'a> Fn(&'a mut T) + Send + Sync + 'static>(bus: &EventBus, priority: i32, handler: F, id: usize) {
  221. HANDLERS.read().expect("failed to lock for reading").get(id).map(|arc| Arc::clone(arc))
  222. .map(|any| Arc::downcast::<Handlers<T>>(any).expect("Wrong id"))
  223. .map(|handlers| {
  224. let mut lock = handlers.0.read().expect("failed to lock for reading");
  225. if lock.len() <= id {
  226. mem::drop(lock);
  227. let mut wlock = handlers.0.write().expect("failed to lock for writing");
  228. if wlock.len() <= id { // another thread may have touched this
  229. let vec = Arc::get_mut(&mut wlock).expect("failed to mutate busses");
  230. let count = id - vec.len() + 1;
  231. vec.reserve_exact(count);
  232. for _ in 0..count {
  233. vec.push(Default::default());
  234. }
  235. }
  236. // there's no way to downgrade a write lock, but as long as we never shrink the
  237. // vecs it should be fine.
  238. mem::drop(wlock);
  239. lock = handlers.0.read().expect("failed to lock for reading");
  240. }
  241. let option = lock.get(bus.id);
  242. // last RwLock
  243. let hooks = option.expect("failed to make vecs");
  244. let hook: (i32, Arc<dyn Fn(&mut T) + Send + Sync + 'static>) = (priority, Arc::new(handler));
  245. let mut wlock = hooks.write().expect("failed to lock for writing");
  246. let vec = Arc::make_mut(&mut wlock);
  247. // would be nice if Result had a .coalesce()
  248. let pos = match vec.binary_search_by(|probe| probe.0.cmp(&priority)) { Ok(p) => p, Err(p) => p };
  249. vec.insert(pos, hook);
  250. }).expect("No such id");
  251. }
  252. static BUS_ID: AtomicUsize = ATOMIC_USIZE_INIT;
  253. lazy_static! {
  254. // this is the closest to high-performance we can get with std
  255. // would be nicer if this didn't lock the whole list
  256. static ref FREED_BUS_IDS: Mutex<LinkedList<usize>> = Mutex::new(LinkedList::new());
  257. }
  258. impl EventBus {
  259. /// Makes a new EventBus.
  260. pub fn new() -> EventBus {
  261. EventBus {
  262. id: FREED_BUS_IDS.lock().unwrap().pop_front().unwrap_or_else(|| BUS_ID.fetch_add(1, AtomicOrdering::SeqCst)),
  263. dropper: Default::default(),
  264. }
  265. }
  266. }
  267. impl Drop for EventBus {
  268. fn drop(&mut self) {
  269. // TODO
  270. }
  271. }
  272. // test with good error messages
  273. #[cfg(test)]
  274. mod useful_test {
  275. use super::{Event, EventBus};
  276. struct MyEvent {
  277. i: i32
  278. }
  279. trait DynEvent : Event {
  280. }
  281. impl DynEvent for MyEvent {
  282. }
  283. impl Event for MyEvent {
  284. }
  285. fn add_handler(e: &mut MyEvent) {
  286. /* adds 1 */
  287. e.i += 1;
  288. }
  289. fn no_handler(e: &mut MyEvent) {
  290. /* does nothing */
  291. e.i += 0;
  292. }
  293. #[test]
  294. fn test_usage_internal() {
  295. let event_bus = EventBus::new();
  296. //let handler_id = event_bus.register(add_handler, 0);
  297. register_hook!(&event_bus, 0, MyEvent, add_handler);
  298. let mut event = MyEvent { i: 3 };
  299. assert_eq!(event.i, 3);
  300. post_event!(&event_bus, &mut event, MyEvent);
  301. post_event!(&event_bus, &mut event, dyn DynEvent);
  302. assert_eq!(event.i, 4);
  303. register_hook!(&event_bus, 1, MyEvent, no_handler);
  304. post_event!(&event_bus, &mut event, MyEvent);
  305. assert_eq!(event.i, 5);
  306. //event_bus.unregister(handler_id);
  307. post_event!(&event_bus, &mut event, MyEvent);
  308. //assert_eq!(event.i, 5);
  309. }
  310. }