From e5baa0f99f1ea059da5217cd329f24f031f6b21c Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 10 Jun 2022 14:34:19 -0700 Subject: [PATCH] event --- crates/libs/windows/src/core/event.rs | 67 ++++++++++++++++----------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/crates/libs/windows/src/core/event.rs b/crates/libs/windows/src/core/event.rs index 0e0b587793..2765e046c9 100644 --- a/crates/libs/windows/src/core/event.rs +++ b/crates/libs/windows/src/core/event.rs @@ -23,6 +23,7 @@ impl Event { pub fn new() -> Self { Self { delegates: Array::new(), swap: Mutex::default(), change: Mutex::default() } } + /// Registers a delegate with the event object. pub fn add(&mut self, delegate: &T) -> Result { let mut _lock_free_drop = Array::new(); @@ -32,7 +33,7 @@ impl Event { for delegate in self.delegates.as_slice() { new_delegates.push(delegate.clone()); } - let delegate = Delegate::new(delegate); + let delegate = Delegate::new(delegate)?; let token = delegate.to_token(); new_delegates.push(delegate); @@ -41,6 +42,7 @@ impl Event { token }) } + /// Revokes a delegate's registration from the event object. pub fn remove(&mut self, token: i64) -> Result<()> { let mut _lock_free_drop = Array::new(); @@ -53,9 +55,7 @@ impl Event { let mut new_delegates = Array::new(); let mut removed = false; if capacity == 0 { - if self.delegates.as_slice()[0].to_token() == token { - removed = true; - } + removed = self.delegates.as_slice()[0].to_token() == token; } else { new_delegates = Array::with_capacity(capacity)?; for delegate in self.delegates.as_slice() { @@ -64,7 +64,6 @@ impl Event { continue; } if capacity == 0 { - debug_assert!(!removed); break; } new_delegates.push(delegate.clone()); @@ -78,6 +77,7 @@ impl Event { } Ok(()) } + /// Clears the event, removing all delegates. pub fn clear(&mut self) { let mut _lock_free_drop = Array::new(); @@ -90,6 +90,7 @@ impl Event { _lock_free_drop = self.delegates.swap(Array::new()); } } + /// Invokes all of the event object's registered delegates with the provided callback. pub fn call Result<()>>(&mut self, mut callback: F) -> Result<()> { let lock_free_calls = { @@ -110,7 +111,7 @@ impl Event { /// A thread-safe reference-counted array of delegates. struct Array { - buffer: *mut Buffer, + buffer: *mut Buffer, len: usize, _phantom: std::marker::PhantomData, } @@ -126,45 +127,52 @@ impl Array { fn new() -> Self { Self { buffer: std::ptr::null_mut(), len: 0, _phantom: std::marker::PhantomData } } + /// Creates a new, empty `Array` with the specified capacity. fn with_capacity(capacity: usize) -> Result { - Ok(Self { buffer: Buffer::new(capacity * std::mem::size_of::>())?, len: 0, _phantom: std::marker::PhantomData }) + Ok(Self { buffer: Buffer::new(capacity)?, len: 0, _phantom: std::marker::PhantomData }) } + /// Swaps the contents of two `Array` objects. fn swap(&mut self, mut other: Self) -> Self { unsafe { std::ptr::swap(&mut self.buffer, &mut other.buffer) }; std::mem::swap(&mut self.len, &mut other.len); other } + /// Returns `true` if the array contains no delegates. fn is_empty(&self) -> bool { self.len == 0 } + /// Returns the number of delegates in the array. fn len(&self) -> usize { self.len } + /// Appends a delegate to the back of the array. fn push(&mut self, delegate: Delegate) { unsafe { - std::ptr::write((*self.buffer).as_mut_ptr::>().add(self.len) as _, delegate); + std::ptr::write((*self.buffer).as_mut_ptr().add(self.len), delegate); self.len += 1; } } + /// Returns a slice containing of all delegates. fn as_slice(&self) -> &[Delegate] { if self.is_empty() { &[] } else { - unsafe { std::slice::from_raw_parts((*self.buffer).as_ptr::>() as _, self.len) } + unsafe { std::slice::from_raw_parts((*self.buffer).as_ptr(), self.len) } } } + /// Returns a mutable slice of all delegates. fn as_mut_slice(&mut self) -> &mut [Delegate] { if self.is_empty() { &mut [] } else { - unsafe { std::slice::from_raw_parts_mut((*self.buffer).as_mut_ptr::>() as _, self.len) } + unsafe { std::slice::from_raw_parts_mut((*self.buffer).as_mut_ptr(), self.len) } } } } @@ -191,28 +199,30 @@ impl Drop for Array { /// A reference-counted buffer. #[repr(C)] -struct Buffer(RefCount); +struct Buffer(RefCount, std::marker::PhantomData); -impl Buffer { +impl Buffer { /// Creates a new `Buffer` with the specified size in bytes. - fn new(size: usize) -> Result<*mut Buffer> { - if size == 0 { + fn new(len: usize) -> Result<*mut Self> { + if len == 0 { Ok(std::ptr::null_mut()) } else { - let alloc_size = std::mem::size_of::() + size; - let header = heap_alloc(alloc_size)? as *mut Buffer; + let alloc_size = std::mem::size_of::() + len * std::mem::size_of::>(); + let header = heap_alloc(alloc_size)? as *mut Self; unsafe { - (*header).0 = RefCount::new(1); + header.write(Self(RefCount::new(1), std::marker::PhantomData)); } Ok(header) } } - /// Returns a raw pointer to the buffer's contents. - fn as_ptr(&self) -> *const T { + + /// Returns a raw pointer to the buffer's contents. The resulting pointer might be uninititalized. + fn as_ptr(&self) -> *const Delegate { unsafe { (self as *const Self).add(1) as *const _ } } - /// Returns a raw mutable pointer to the buffer's contents. - fn as_mut_ptr(&mut self) -> *mut T { + + /// Returns a raw mutable pointer to the buffer's contents. The resulting pointer might be uninititalized. + fn as_mut_ptr(&mut self) -> *mut Delegate { unsafe { (self as *mut Self).add(1) as *mut _ } } } @@ -220,21 +230,21 @@ impl Buffer { /// 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 { +enum Delegate { Direct(T), Indirect(AgileReference), } impl Delegate { /// Creates a new `Delegate`, containing a suitable reference to the specified delegate. - fn new(delegate: &T) -> Self { - if delegate.cast::().is_err() { - if let Ok(delegate) = AgileReference::new(delegate) { - return Self::Indirect(delegate); - } + fn new(delegate: &T) -> Result { + if delegate.cast::().is_ok() { + Ok(Self::Direct(delegate.clone())) + } else { + Ok(Self::Indirect(AgileReference::new(delegate)?)) } - Self::Direct(delegate.clone()) } + /// Returns an encoded token to identify the delegate. fn to_token(&self) -> i64 { unsafe { @@ -244,6 +254,7 @@ impl Delegate { } } } + /// Invokes the delegates with the provided callback. fn call Result<()>>(&self, mut callback: F) -> Result<()> { match self {