summaryrefslogtreecommitdiff
path: root/vendor/windows-core/src/event.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/windows-core/src/event.rs')
-rw-r--r--vendor/windows-core/src/event.rs144
1 files changed, 0 insertions, 144 deletions
diff --git a/vendor/windows-core/src/event.rs b/vendor/windows-core/src/event.rs
deleted file mode 100644
index 3951ef2c..00000000
--- a/vendor/windows-core/src/event.rs
+++ /dev/null
@@ -1,144 +0,0 @@
-use super::*;
-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.
-pub struct Event<T: Interface> {
- delegates: RwLock<Option<Arc<[Delegate<T>]>>>,
-}
-
-unsafe impl<T: Interface> Send for Event<T> {}
-unsafe impl<T: Interface> Sync for Event<T> {}
-
-impl<T: Interface> Default for Event<T> {
- fn default() -> Self {
- Self::new()
- }
-}
-
-impl<T: Interface> Event<T> {
- /// Creates a new, empty `Event<T>`.
- pub const fn new() -> Self {
- Self {
- delegates: RwLock::new(None),
- }
- }
-
- /// Registers a delegate with the event object.
- pub fn add(&self, delegate: &T) -> Result<i64> {
- let new_delegate = Delegate::new(delegate)?;
- let token = new_delegate.to_token();
- let new_iter = once(new_delegate);
- let mut guard = self.delegates.write().unwrap();
-
- let new_list = if let Some(old_delegates) = guard.as_ref() {
- Arc::from_iter(old_delegates.iter().cloned().chain(new_iter))
- } else {
- Arc::from_iter(new_iter)
- };
-
- 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.
- pub fn remove(&self, token: i64) {
- let mut guard = self.delegates.write().unwrap();
- let mut old_list = None;
- if let Some(old_delegates) = guard.as_ref() {
- // `self.delegates` is only modified if the token is found.
- if let 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.
- pub fn clear(&self) {
- let mut 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.
- pub fn call<F: FnMut(&T) -> Result<()>>(&self, mut callback: F) {
- let delegates = {
- let guard = self.delegates.read().unwrap();
- if let Some(delegates) = guard.as_ref() {
- delegates.clone()
- } else {
- // No delegates to call.
- return;
- }
- // <-- lock is released here
- };
-
- for delegate in delegates.iter() {
- if let Err(error) = delegate.call(&mut callback) {
- const RPC_E_SERVER_UNAVAILABLE: HRESULT = HRESULT(-2147023174); // HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)
- if matches!(
- error.code(),
- imp::RPC_E_DISCONNECTED | imp::JSCRIPT_E_CANTEXECUTE | RPC_E_SERVER_UNAVAILABLE
- ) {
- self.remove(delegate.to_token());
- }
- }
- }
- }
-}
-
-/// 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 {
- match self {
- 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<()> {
- match self {
- Self::Direct(delegate) => callback(delegate),
- Self::Indirect(delegate) => callback(&delegate.resolve()?),
- }
- }
-}