use std::collections::{ HashSet, HashMap };
use std::any::{ Any, TypeId };
use shared_mutex::{ SharedMutex, MappedSharedMutexReadGuard, MappedSharedMutexWriteGuard };
use components;
pub trait Handler {
fn run(&self, Vec<MappedSharedMutexReadGuard<Any>>, Vec<MappedSharedMutexWriteGuard<Any>>);
fn component_types(&self) -> Vec<TypeId>;
fn mut_component_types(&self) -> Vec<TypeId>;
}
#[derive(Clone)]
pub struct Event {
pub name: String,
pub get_handler_instances: fn () -> Vec<Box<Handler>>
}
lazy_static! {
pub static ref THIS_TICK_NEW_EVENTS: SharedMutex<HashSet<String>> = SharedMutex::new(HashSet::new());
pub static ref NEXT_TICK_NEW_EVENTS: SharedMutex<HashSet<String>> = SharedMutex::new(HashSet::new());
pub static ref REGISTERED_EVENTS: SharedMutex<HashMap<String, Event>> = SharedMutex::new(HashMap::new());
}
pub fn trigger_this_tick(event_name: &String) {
let mut new_events_set = THIS_TICK_NEW_EVENTS.write().expect("THIS_TICK_NEW_EVENTS mutex was corrupted.");
new_events_set.insert(event_name.clone());
}
pub fn trigger_next_tick(event_name: &String) {
let mut new_events_set = NEXT_TICK_NEW_EVENTS.write().expect("NEXT_TICK_NEW_EVENTS mutex was corrupted.");
new_events_set.insert(event_name.clone());
}
pub fn register_event(event : Event) {
let mut events = REGISTERED_EVENTS.write().expect("REGISTERED_EVENTS mutex was corrupted.");
events.insert(event.name.clone(), event);
}
pub fn has_events() -> bool {
THIS_TICK_NEW_EVENTS.read().expect("THIS_TICK_NEW_EVENTS mutex was corrupted").len() > 0
}
pub fn run_events() {
let events : Vec<Event>;
{
let event_names : Vec<String>;
{
let mut event_names_lock = THIS_TICK_NEW_EVENTS.write().expect("THIS_TICK_NEW_EVENTS mutex was corrupted");
event_names = event_names_lock.drain().collect();
}
let events_lock = REGISTERED_EVENTS.read().expect("REGISTERED_EVENTS mutex was corrupted");
events = event_names.iter().map(|n|
events_lock.get(&*n).cloned().expect(&format!("Unknown event triggered: {}", n))
).collect();
}
let handlers = events.iter().flat_map(|e| (e.get_handler_instances)() );
for handler in handlers {
let component_types = handler.component_types();
let mut_component_types = handler.mut_component_types();
let mut locks : Vec<MappedSharedMutexReadGuard<Any>>= vec![];
let mut mut_locks : Vec<MappedSharedMutexWriteGuard<Any>>= vec![];
for typ in component_types {
locks.push(components::get_components_read_lock(typ));
}
for typ in mut_component_types {
mut_locks.push(components::get_components_write_lock(typ));
}
handler.run(locks, mut_locks)
}
}
pub fn next_tick() {
let mut this_tick_events = THIS_TICK_NEW_EVENTS.write().expect("THIS_TICK_NEW_EVENTS mutex was corrupted");
let mut next_events_lock = NEXT_TICK_NEW_EVENTS.write().expect("THIS_TICK_NEW_EVENTS mutex was corrupted");
for next_event in next_events_lock.drain() {
this_tick_events.insert(next_event);
}
}
#[macro_export]
macro_rules! event {
( $name:ident, $( $field_name:ident : $field_typ:ty ),* ) => (
pub mod $name {
use shared_mutex::{ SharedMutex, MappedSharedMutexWriteGuard, MappedSharedMutexReadGuard };
use std::any::{ Any, TypeId };
use $crate::events;
use uuid::Uuid;
use std::sync::Arc;
#[derive(PartialEq,Eq,Clone)]
pub struct Data {
$(pub $field_name : $field_typ),*
}
pub type HandlerFn = fn(Arc<Any>, &Vec<Data>, Vec<MappedSharedMutexReadGuard<Any>>, Vec<MappedSharedMutexWriteGuard<Any>>);
pub struct Handler {
handler_fn: HandlerFn,
state: Arc<Any+Sync+Send>,
component_types: Vec<TypeId>,
mut_component_types: Vec<TypeId>
}
pub struct HandlerInstance {
handler_fn: HandlerFn,
state: Arc<Any+Sync+Send>,
component_types: Vec<TypeId>,
mut_component_types: Vec<TypeId>,
data: Vec<Data>
}
impl HandlerInstance {
pub fn new(h: &Handler, d: Vec<Data>) -> HandlerInstance {
HandlerInstance {
handler_fn: h.handler_fn,
state: h.state.clone(),
component_types: h.component_types.clone(),
mut_component_types: h.mut_component_types.clone(),
data: d
}
}
}
impl events::Handler for HandlerInstance {
fn run(&self, components: Vec<MappedSharedMutexReadGuard<Any>>, mut_components: Vec<MappedSharedMutexWriteGuard<Any>>) {
let handler_fn = self.handler_fn;
let data = &self.data;
let state = self.state.clone();
handler_fn(state, data, components, mut_components)
}
fn component_types(&self) -> Vec<TypeId> { self.component_types.clone() }
fn mut_component_types(&self) -> Vec<TypeId> { self.mut_component_types.clone() }
}
lazy_static! {
pub static ref EVENT_UUID: String = Uuid::new_v4().simple().to_string();
pub static ref HANDLERS: SharedMutex<Vec<Handler>> = SharedMutex::new(vec![]);
pub static ref THIS_TICK_DATA: SharedMutex<Vec<Data>> = SharedMutex::new(vec![]);
}
pub fn trigger($($field_name : $field_typ),*) {
let argument = Data {
$($field_name : $field_name),*
};
let mut data = THIS_TICK_DATA.write().expect("THIS_TICK_DATA mutex corrupted");
data.push(argument);
events::trigger_this_tick(&*EVENT_UUID);
}
pub fn register_handler(state: Arc<Any+Sync+Send>, handler_fn: HandlerFn, component_types: Vec<TypeId>, mut_component_types: Vec<TypeId>) {
let mut handlers = HANDLERS.write().expect("Events HANDLERS mutex corrupted");
let handler = Handler {
handler_fn : handler_fn,
state: state,
component_types : component_types.clone(),
mut_component_types : mut_component_types.clone()
};
handlers.push(handler);
let event = events::Event {
name: (&*EVENT_UUID).clone(),
get_handler_instances: get_handler_instances
};
events::register_event(event)
}
pub fn get_handler_instances() -> Vec<Box<events::Handler>> {
let mut data_old = THIS_TICK_DATA.write().expect("TICK DATA mutex corrupted");
let data : Vec<Data> = data_old.drain(..).collect();
let handlers_lock = HANDLERS.read().expect("HANDLERS mutex corrupted");
handlers_lock.iter().map(|h|
Box::new(HandlerInstance::new(h, data.clone())) as Box<events::Handler>
).collect()
}
pub fn clear_handlers() {
let mut handlers = HANDLERS.write().expect("Events HANDLERS mutex corrupted");
handlers.clear();
}
}
)
}
#[macro_export]
macro_rules! sync_event {
( $name:ident, $field_name:ident : $field_typ:ty ) => (
pub mod $name {
use shared_mutex::SharedMutex;
use std::sync::Arc;
use std::any::{ Any };
pub struct Handler {
pub handler_fn: HandlerFn,
pub state: Arc<Any+Send+Sync>
}
pub type Argument<'a,'b> = $field_typ;
pub type HandlerFn = fn(Arc<Any+Send+Sync>, Argument);
lazy_static! {
pub static ref HANDLERS: SharedMutex<Vec<Handler>> = SharedMutex::new(vec![]);
}
pub fn trigger<'a, 'b>($field_name : $field_typ) {
let handlers = HANDLERS.read().expect("HANDLERS mutex corrupted");
for handler in handlers.iter() {
(handler.handler_fn)(handler.state.clone(), $field_name);
}
}
pub fn register_handler(state: Arc<Any+Send+Sync>, handler_fn: HandlerFn) {
let mut handlers = HANDLERS.write().expect("Events HANDLERS mutex corrupted");
let handler = Handler {
handler_fn: handler_fn,
state: state
};
handlers.push(handler);
}
pub fn clear_handlers() {
let mut handlers = HANDLERS.write().expect("Events HANDLERS mutex corrupted");
handlers.clear();
}
}
)
}