From 5b7b4f1e12c0c9d8e2c555822d91d3301a4366ff Mon Sep 17 00:00:00 2001 From: Daniel Griffen Date: Sun, 28 Oct 2018 19:32:00 -0700 Subject: [PATCH] make cancellation a type property --- src/lib.rs | 55 ++++++++++++++++++++++++++++++++------- tests/dyn_events.rs | 63 +++++++++++++++++++++++++-------------------- 2 files changed, 80 insertions(+), 38 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 105b7ef..58d854c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,14 +56,6 @@ macro_rules! post_event { // event setup, this may evaluate to any type. let event: &mut _ = $e; { - // it is a logic error for an event's cancellability to change based on its value. - static CANCELLABLE: ::std::sync::atomic::AtomicBool = ::std::sync::atomic::ATOMIC_BOOL_INIT; - static CANCELLABLE_INIT: ::std::sync::Once = ::std::sync::ONCE_INIT; - CANCELLABLE_INIT.call_once(|| { - CANCELLABLE.store(<$crate::Event>::cancellable(event), std::sync::atomic::Ordering::Relaxed); - }); - let cancellable = CANCELLABLE.load(std::sync::atomic::Ordering::Relaxed); - // event type setup static EVENT_ID: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::ATOMIC_USIZE_INIT; static EVENT_ID_INIT: ::std::sync::Once = ::std::sync::ONCE_INIT; @@ -79,11 +71,50 @@ macro_rules! post_event { let handlers = $crate::get_post_targets::<$t>(bus, event, id); for (_pri, fun) in handlers.iter() { fun(event); - if cancellable && <$t as $crate::Event>::cancelled(event) { + } + } + } + } +} + +/// Posts an event. +/// +/// Usage: `post_event!(bus, type, event)` +#[macro_export] +macro_rules! post_event_cancellable { + // TODO allow multiple $t:ty at once and re-#[doc(hidden)] the low-level get_post_targets and + // get_event_id + ($b:expr, $t:ty, $e:expr) => { + { + // hygiene + let bus: &$crate::EventBus = $b; + // event setup, this may evaluate to any type. + let event: &mut _ = $e; + { + fn test(e: &C) { + + } + + test(event); + // event type setup + static EVENT_ID: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::ATOMIC_USIZE_INIT; + static EVENT_ID_INIT: ::std::sync::Once = ::std::sync::ONCE_INIT; + // no generics allowed. + static DUMMY: ::std::marker::PhantomData = ::std::marker::PhantomData; + EVENT_ID_INIT.call_once(|| { + EVENT_ID.store($crate::get_event_id::<$t>(), std::sync::atomic::Ordering::Relaxed); + }); + let id = EVENT_ID.load(std::sync::atomic::Ordering::Relaxed); + + // handler retrieval and invokation + let handlers = $crate::get_post_targets::<$t>(bus, event, id); + for (_pri, fun) in handlers.iter() { + fun(event as &mut $t); + if event.cancelled() { break; } } - cancellable && <$t as $crate::Event>::cancelled(event) + event.cancelled() } } } @@ -101,6 +132,10 @@ pub trait Event: 'static { fn cancellable(&self) -> bool { false } +} + +/// Basic trait for defining an event. +pub trait Cancellable: 'static { /// Returns whether this event has been cancelled. fn cancelled(&self) -> bool { diff --git a/tests/dyn_events.rs b/tests/dyn_events.rs index 0407f7f..8ea4599 100644 --- a/tests/dyn_events.rs +++ b/tests/dyn_events.rs @@ -1,53 +1,60 @@ #[macro_use] extern crate eventbus; -use eventbus::{Event, EventBus}; +use std::fmt::Debug; +use eventbus::{Event, EventBus, Cancellable}; -trait MyEvent : Event { - fn get_i(&self) -> i32; - fn set_i(&mut self, i32); +trait MyEvent : Event + Debug { } +trait MyExtraEvent : MyEvent + Cancellable { +} + +#[derive(Debug)] struct MyEventImpl { i: i32 } +#[derive(Debug)] +struct MyExtraEventImpl { + i: i32 +} + impl Event for MyEventImpl { } + impl MyEvent for MyEventImpl { - fn get_i(&self) -> i32 { - self.i - } - fn set_i(&mut self, i: i32) { - self.i = i; - } } -fn add_handler(e: &mut MyEvent) { - /* adds 1 */ - let i = e.get_i(); - e.set_i(i+1); +impl Event for MyExtraEventImpl { } -fn no_handler(e: &mut MyEvent) { - /* does nothing */ - let i = e.get_i(); - e.set_i(i); +impl MyEvent for MyExtraEventImpl { +} + +impl MyExtraEvent for MyExtraEventImpl { +} + +impl Cancellable for MyExtraEventImpl { + +} + +fn on_myevent(evt: &mut dyn MyEvent) { + println!("Got event for inspection and manipulation: {:?}", evt); +} + +fn on_myextraevent(evt: &mut dyn MyExtraEvent) { + println!("Got event for inspection, manipulation, and cancellation: {:?}", evt); } #[test] fn test_dyn_usage() { let event_bus = EventBus::new(); - //let handler_id = event_bus.register(add_handler, 0); - register_hook!(&event_bus, 0, dyn MyEvent, add_handler); let mut event = MyEventImpl { i: 3 }; - assert_eq!(event.i, 3); + let mut extraEvent = MyExtraEventImpl { i: 4 }; + //let handler_id = event_bus.register(add_handler, 0); + register_hook!(&event_bus, 0, dyn MyEvent, on_myevent); + register_hook!(&event_bus, 1, dyn MyExtraEvent, on_myextraevent); post_event!(&event_bus, dyn MyEvent, &mut event); - assert_eq!(event.i, 4); - register_hook!(&event_bus, 1, dyn MyEvent, no_handler); - post_event!(&event_bus, dyn MyEvent, &mut event); - assert_eq!(event.i, 5); - //event_bus.unregister(handler_id); - post_event!(&event_bus, dyn MyEvent, &mut event); - //assert_eq!(event.i, 5); + post_event_cancellable!(&event_bus, dyn MyExtraEvent, &mut extraEvent); }