usesuper::*; use core::{iter::once, mem::transmute_copy}; use std::sync::{Arc, RwLock};
/// A type that you can use to declare and implement an event of a specified delegate type. /// /// The implementation is thread-safe and designed to avoid contention between events being /// raised and delegates being added or removed. pubstruct Event<T: Interface> {
delegates: RwLock<Option<Arc<[Delegate<T>]>>>,
}
unsafeimpl<T: Interface> Send for Event<T> {} unsafeimpl<T: Interface> Sync for Event<T> {}
let old_list = guard.replace(new_list);
drop(guard);
drop(old_list); // drop the old delegates _after_ releasing lock
Ok(token)
}
/// Revokes a delegate's registration from the event object. pubfn remove(&self, token: i64) { letmut guard = self.delegates.write().unwrap(); letmut old_list = None; iflet Some(old_delegates) = guard.as_ref() { // `self.delegates` is only modified if the token is found. iflet Some(i) = old_delegates
.iter()
.position(|old_delegate| old_delegate.to_token() == token)
{ let new_list = Arc::from_iter(
old_delegates[..i]
.iter()
.chain(old_delegates[i + 1..].iter())
.cloned(),
);
old_list = guard.replace(new_list);
}
}
drop(guard);
drop(old_list); // drop the old delegates _after_ releasing lock
}
/// Clears the event, removing all delegates. pubfn clear(&self) { letmut guard = self.delegates.write().unwrap(); let old_list = guard.take();
drop(guard);
drop(old_list); // drop the old delegates _after_ releasing lock
}
/// Invokes all of the event object's registered delegates with the provided callback. pubfn call<F: FnMut(&T) -> Result<()>>(&self, mut callback: F) { let delegates = { let guard = self.delegates.read().unwrap(); iflet Some(delegates) = guard.as_ref() {
delegates.clone()
} else { // No delegates to call. return;
} // <-- lock is released here
};
/// Holds either a direct or indirect reference to a delegate. A direct reference is typically /// agile while an indirect reference is an agile wrapper. #[derive(Clone)] enum Delegate<T> {
Direct(T),
Indirect(AgileReference<T>),
}
impl<T: Interface> Delegate<T> { /// Creates a new `Delegate<T>`, containing a suitable reference to the specified delegate. fn new(delegate: &T) -> Result<Self> { if delegate.cast::<imp::IAgileObject>().is_ok() {
Ok(Self::Direct(delegate.clone()))
} else {
Ok(Self::Indirect(AgileReference::new(delegate)?))
}
}
/// Returns an encoded token to identify the delegate. fn to_token(&self) -> i64 { unsafe { matchself { Self::Direct(delegate) => imp::EncodePointer(transmute_copy(delegate)) as i64, Self::Indirect(delegate) => imp::EncodePointer(transmute_copy(delegate)) as i64,
}
}
}
/// Invokes the delegates with the provided callback. fn call<F: FnMut(&T) -> Result<()>>(&self, mut callback: F) -> Result<()> { matchself { Self::Direct(delegate) => callback(delegate), Self::Indirect(delegate) => callback(&delegate.resolve()?),
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.