usesuper::*; use core::ffi::c_void; use core::marker::PhantomData; use core::mem::{size_of, transmute_copy}; use core::ptr::null_mut; use std::sync::Mutex;
/// 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> {
swap: Mutex<()>,
change: Mutex<()>,
delegates: Array<T>,
}
impl<T: Interface> Array<T> { /// Creates a new, empty `Array<T>` with no capacity. fn new() -> Self { Self {
buffer: null_mut(),
len: 0,
_phantom: PhantomData,
}
}
/// Creates a new, empty `Array<T>` with the specified capacity. fn with_capacity(capacity: usize) -> Result<Self> {
Ok(Self {
buffer: Buffer::new(capacity)?,
len: 0,
_phantom: PhantomData,
})
}
/// Swaps the contents of two `Array<T>` objects. fn swap(&mutself, mut other: Self) -> Self { unsafe { core::ptr::swap(&mutself.buffer, &mut other.buffer) };
core::mem::swap(&mutself.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(&mutself, delegate: Delegate<T>) { unsafe {
(*self.buffer).as_mut_ptr().add(self.len).write(delegate); self.len += 1;
}
}
/// Returns a slice containing of all delegates. fn as_slice(&self) -> &[Delegate<T>] { ifself.is_empty() {
&[]
} else { unsafe { core::slice::from_raw_parts((*self.buffer).as_ptr(), self.len) }
}
}
/// Returns a mutable slice of all delegates. fn as_mut_slice(&mutself) -> &mut [Delegate<T>] { ifself.is_empty() {
&mut []
} else { unsafe { core::slice::from_raw_parts_mut((*self.buffer).as_mut_ptr(), self.len) }
}
}
}
impl<T: Interface> Drop for Array<T> { fn drop(&mutself) { unsafe { if !self.is_empty() && (*self.buffer).0.release() == 0 {
core::ptr::drop_in_place(self.as_mut_slice());
heap_free(self.buffer as _)
}
}
}
}
/// A reference-counted buffer. #[repr(C)] #[repr(align(8))] struct Buffer<T>(imp::RefCount, PhantomData<T>);
impl<T: Interface> Buffer<T> { /// Creates a new `Buffer` with the specified size in bytes. fn new(len: usize) -> Result<*mutSelf> { if len == 0 {
Ok(null_mut())
} else { let alloc_size = size_of::<Self>() + len * size_of::<Delegate<T>>(); let header = heap_alloc(alloc_size)? as *mutSelf; unsafe {
header.write(Self(imp::RefCount::new(1), PhantomData));
}
Ok(header)
}
}
/// Returns a raw pointer to the buffer's contents. The resulting pointer might be uninititalized. fn as_ptr(&self) -> *const Delegate<T> { unsafe { (selfas *constSelf).add(1) as *const _ }
}
/// Returns a raw mutable pointer to the buffer's contents. The resulting pointer might be uninititalized. fn as_mut_ptr(&mutself) -> *mut Delegate<T> { unsafe { (selfas *mutSelf).add(1) as *mut _ }
}
}
/// 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()?),
}
}
}
/// Allocate memory of size `bytes` using `malloc` - the `Event` implementation does not /// need to use any particular allocator so `HeapAlloc` need not be used. fn heap_alloc(bytes: usize) -> crate::Result<*mut c_void> { let ptr: *mut c_void = unsafe { extern"C" { fn malloc(bytes: usize) -> *mut c_void;
}
malloc(bytes)
};
if ptr.is_null() {
Err(Error::from_hresult(imp::E_OUTOFMEMORY))
} else {
Ok(ptr)
}
}
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.