Move cancellable to the type system and implement multi-parenting #1
67
src/lib.rs
67
src/lib.rs
|
@ -49,21 +49,14 @@ macro_rules! register_hook {
|
||||||
macro_rules! post_event {
|
macro_rules! post_event {
|
||||||
// TODO allow multiple $t:ty at once and re-#[doc(hidden)] the low-level get_post_targets and
|
// TODO allow multiple $t:ty at once and re-#[doc(hidden)] the low-level get_post_targets and
|
||||||
// get_event_id
|
// get_event_id
|
||||||
($b:expr, $t:ty, $e:expr) => {
|
($b:expr, $e:expr, $($t:ty),+) => {
|
||||||
{
|
{
|
||||||
// hygiene
|
// hygiene
|
||||||
let bus: &$crate::EventBus = $b;
|
let bus: &$crate::EventBus = $b;
|
||||||
// event setup, this may evaluate to any type.
|
// event setup, this may evaluate to any type.
|
||||||
let event: &mut _ = $e;
|
let event: &mut _ = $e;
|
||||||
{
|
{
|
||||||
// it is a logic error for an event's cancellability to change based on its value.
|
let _ = ($({
|
||||||
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
|
// event type setup
|
||||||
static EVENT_ID: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::ATOMIC_USIZE_INIT;
|
static EVENT_ID: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::ATOMIC_USIZE_INIT;
|
||||||
static EVENT_ID_INIT: ::std::sync::Once = ::std::sync::ONCE_INIT;
|
static EVENT_ID_INIT: ::std::sync::Once = ::std::sync::ONCE_INIT;
|
||||||
|
@ -73,17 +66,59 @@ macro_rules! post_event {
|
||||||
EVENT_ID.store($crate::get_event_id::<$t>(), std::sync::atomic::Ordering::Relaxed);
|
EVENT_ID.store($crate::get_event_id::<$t>(), std::sync::atomic::Ordering::Relaxed);
|
||||||
});
|
});
|
||||||
let id = EVENT_ID.load(std::sync::atomic::Ordering::Relaxed);
|
let id = EVENT_ID.load(std::sync::atomic::Ordering::Relaxed);
|
||||||
|
|
||||||
// handler retrieval and invokation
|
|
||||||
let event: &mut $t = event;
|
|
||||||
let handlers = $crate::get_post_targets::<$t>(bus, event, id);
|
let handlers = $crate::get_post_targets::<$t>(bus, event, id);
|
||||||
|
|
||||||
for (_pri, fun) in handlers.iter() {
|
for (_pri, fun) in handlers.iter() {
|
||||||
fun(event);
|
fun(event);
|
||||||
if cancellable && <$t as $crate::Event>::cancelled(event) {
|
}
|
||||||
|
},)+); // big tuple of (Handlers<type>, Handlers<type>, Handlers<type>, Handlers<type>, ...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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, $e:expr, $($t:ty),+) => {
|
||||||
|
{
|
||||||
|
// hygiene
|
||||||
|
let bus: &$crate::EventBus = $b;
|
||||||
|
// event setup, this may evaluate to any type.
|
||||||
|
let event: &mut _ = $e;
|
||||||
|
{
|
||||||
|
fn test<C: Cancellable>(e: &C) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
test(event);
|
||||||
|
let cancelled = [$({
|
||||||
|
// 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<dyn Fn(&mut $t) + Send + Sync> = ::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);
|
||||||
|
let handlers = $crate::get_post_targets::<$t>(bus, event, id);
|
||||||
|
|
||||||
|
for (_pri, fun) in handlers.iter() {
|
||||||
|
if Cancellable::cancelled(event) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
fun(event as &mut $t);
|
||||||
}
|
}
|
||||||
cancellable && <$t as $crate::Event>::cancelled(event)
|
|
||||||
|
event.cancelled()
|
||||||
|
},)+]; // big tuple of (Handlers<type>, Handlers<type>, Handlers<type>, Handlers<type>, ...)
|
||||||
|
|
||||||
|
cancelled.iter().fold(false, |n, i| n || *i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,6 +136,10 @@ pub trait Event: 'static {
|
||||||
fn cancellable(&self) -> bool {
|
fn cancellable(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Basic trait for defining an event.
|
||||||
|
pub trait Cancellable: 'static {
|
||||||
|
|
||||||
/// Returns whether this event has been cancelled.
|
/// Returns whether this event has been cancelled.
|
||||||
fn cancelled(&self) -> bool {
|
fn cancelled(&self) -> bool {
|
||||||
|
|
|
@ -27,12 +27,12 @@ fn test_basic_usage() {
|
||||||
register_hook!(&event_bus, 0, MyEvent, add_handler);
|
register_hook!(&event_bus, 0, MyEvent, add_handler);
|
||||||
let mut event = MyEvent { i: 3 };
|
let mut event = MyEvent { i: 3 };
|
||||||
assert_eq!(event.i, 3);
|
assert_eq!(event.i, 3);
|
||||||
post_event!(&event_bus, MyEvent, &mut event);
|
post_event!(&event_bus, &mut event, MyEvent);
|
||||||
assert_eq!(event.i, 4);
|
assert_eq!(event.i, 4);
|
||||||
register_hook!(&event_bus, 1, MyEvent, no_handler);
|
register_hook!(&event_bus, 1, MyEvent, no_handler);
|
||||||
post_event!(&event_bus, MyEvent, &mut event);
|
post_event!(&event_bus, &mut event, MyEvent);
|
||||||
assert_eq!(event.i, 5);
|
assert_eq!(event.i, 5);
|
||||||
//event_bus.unregister(handler_id);
|
//event_bus.unregister(handler_id);
|
||||||
post_event!(&event_bus, MyEvent, &mut event);
|
post_event!(&event_bus, &mut event, MyEvent);
|
||||||
//assert_eq!(event.i, 5);
|
//assert_eq!(event.i, 5);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,53 +1,60 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate eventbus;
|
extern crate eventbus;
|
||||||
|
|
||||||
use eventbus::{Event, EventBus};
|
use std::fmt::Debug;
|
||||||
|
use eventbus::{Event, EventBus, Cancellable};
|
||||||
|
|
||||||
trait MyEvent : Event {
|
trait MyEvent : Event + Debug {
|
||||||
fn get_i(&self) -> i32;
|
|
||||||
fn set_i(&mut self, i32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait MyExtraEvent : MyEvent + Cancellable {
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct MyEventImpl {
|
struct MyEventImpl {
|
||||||
i: i32
|
i: i32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct MyExtraEventImpl {
|
||||||
|
i: i32
|
||||||
|
}
|
||||||
|
|
||||||
impl Event for MyEventImpl {
|
impl Event for MyEventImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MyEvent 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) {
|
impl Event for MyExtraEventImpl {
|
||||||
/* adds 1 */
|
|
||||||
let i = e.get_i();
|
|
||||||
e.set_i(i+1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn no_handler(e: &mut MyEvent) {
|
impl MyEvent for MyExtraEventImpl {
|
||||||
/* does nothing */
|
}
|
||||||
let i = e.get_i();
|
|
||||||
e.set_i(i);
|
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]
|
#[test]
|
||||||
fn test_dyn_usage() {
|
fn test_dyn_usage() {
|
||||||
let event_bus = EventBus::new();
|
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 };
|
let mut event = MyEventImpl { i: 3 };
|
||||||
assert_eq!(event.i, 3);
|
let mut extraEvent = MyExtraEventImpl { i: 4 };
|
||||||
post_event!(&event_bus, dyn MyEvent, &mut event);
|
//let handler_id = event_bus.register(add_handler, 0);
|
||||||
assert_eq!(event.i, 4);
|
register_hook!(&event_bus, 0, dyn MyEvent, on_myevent);
|
||||||
register_hook!(&event_bus, 1, dyn MyEvent, no_handler);
|
register_hook!(&event_bus, 1, dyn MyExtraEvent, on_myextraevent);
|
||||||
post_event!(&event_bus, dyn MyEvent, &mut event);
|
post_event!(&event_bus, &mut event, dyn MyEvent);
|
||||||
assert_eq!(event.i, 5);
|
post_event_cancellable!(&event_bus, &mut extraEvent, dyn MyExtraEvent, dyn MyEvent);
|
||||||
//event_bus.unregister(handler_id);
|
|
||||||
post_event!(&event_bus, dyn MyEvent, &mut event);
|
|
||||||
//assert_eq!(event.i, 5);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue