feat: use arc & clone to remove trait bound from T

This commit is contained in:
Naxdy 2025-03-07 11:18:10 +01:00
commit d764a8d5fb
Signed by: Naxdy
GPG key ID: CC15075846BCE91B
4 changed files with 75 additions and 67 deletions

View file

@ -11,5 +11,5 @@ tokio-macros = { version = "2.5.0", optional = true }
thiserror = { version = "2.0.12" } thiserror = { version = "2.0.12" }
[features] [features]
default = [ ] default = [ "tokio" ]
tokio = [ "dep:tokio", "dep:tokio-macros" ] tokio = [ "dep:tokio", "dep:tokio-macros" ]

View file

@ -10,7 +10,7 @@ Simple Events is a dead simple event library for Rust, providing functionality t
use simple_events::*; use simple_events::*;
// An event struct can be almost anything that implements `Copy` // An event struct can be almost anything that implements `Copy`
#[derive(Clone, Copy, Debug)] #[derive(Debug)]
struct Dummy; struct Dummy;
// A handler function must take in exactly 1 argument of type `Event<T>`. // A handler function must take in exactly 1 argument of type `Event<T>`.
@ -37,7 +37,7 @@ fn main() {
```rust ```rust
use simple_events::*; use simple_events::*;
#[derive(Clone, Copy, Debug)] #[derive(Debug)]
struct Dummy; struct Dummy;
fn main() { fn main() {

View file

@ -18,18 +18,18 @@ type PinnedOutput = Pin<Box<dyn Future<Output = ()> + Send>>;
struct KeyWrapper<T>(PhantomData<T>) struct KeyWrapper<T>(PhantomData<T>)
where where
T: Sized + Sync + Send + Copy; T: Sized + Sync + Send;
impl<T> Key for KeyWrapper<T> impl<T> Key for KeyWrapper<T>
where where
T: Sized + Send + Sync + Copy + 'static, T: Sized + Send + Sync + 'static,
{ {
type Value = Vec<Arc<AsyncEventHandler<T>>>; type Value = Vec<Arc<AsyncEventHandler<T>>>;
} }
pub struct AsyncEventHandler<T> pub struct AsyncEventHandler<T>
where where
T: Sized + Send + Sync + Copy + 'static, T: Sized + Send + Sync + 'static,
{ {
handle_func: Box<dyn (Fn(Event<T>) -> PinnedOutput) + Send + Sync>, handle_func: Box<dyn (Fn(Event<T>) -> PinnedOutput) + Send + Sync>,
fn_id: TypeId, fn_id: TypeId,
@ -38,18 +38,18 @@ where
impl<T> PartialEq for AsyncEventHandler<T> impl<T> PartialEq for AsyncEventHandler<T>
where where
T: Sized + Send + Sync + Copy, T: Sized + Send + Sync,
{ {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.fn_id == other.fn_id self.fn_id == other.fn_id
} }
} }
impl<T> Eq for AsyncEventHandler<T> where T: Sized + Send + Sync + Copy {} impl<T> Eq for AsyncEventHandler<T> where T: Sized + Send + Sync {}
impl<T> AsyncEventHandler<T> impl<T> AsyncEventHandler<T>
where where
T: Sized + Send + Sync + Copy, T: Sized + Send + Sync,
{ {
fn handle_event(&self, event: Event<T>) -> PinnedOutput { fn handle_event(&self, event: Event<T>) -> PinnedOutput {
(self.handle_func)(event) (self.handle_func)(event)
@ -58,7 +58,7 @@ where
impl<T, F, Fu> From<F> for AsyncEventHandler<T> impl<T, F, Fu> From<F> for AsyncEventHandler<T>
where where
T: Send + Sync + Sized + Copy, T: Send + Sync + Sized,
Fu: Future<Output = ()> + Send + 'static, Fu: Future<Output = ()> + Send + 'static,
F: (Fn(Event<T>) -> Fu) + Send + Sync + 'static, F: (Fn(Event<T>) -> Fu) + Send + Sync + 'static,
{ {
@ -76,7 +76,7 @@ where
impl<T> From<&AsyncEventHandler<T>> for EventHandlerRef<T> impl<T> From<&AsyncEventHandler<T>> for EventHandlerRef<T>
where where
T: Send + Sync + Sized + Copy, T: Send + Sync + Sized,
{ {
fn from(value: &AsyncEventHandler<T>) -> Self { fn from(value: &AsyncEventHandler<T>) -> Self {
Self { Self {
@ -106,7 +106,7 @@ impl<F, T> From<AsyncEventHandlerRef<T, F>> for EventHandlerRef<T> {
/// parameter of type `Event<T>` where `T` is the type of event struct that it wants to /// parameter of type `Event<T>` where `T` is the type of event struct that it wants to
/// handle, and returns a `Future<Output = ()>`. /// handle, and returns a `Future<Output = ()>`.
/// ///
pub async fn add_event_handler<T: Send + Sync + Copy + Sized + 'static>( pub async fn add_event_handler<T: Send + Sync + Sized + 'static>(
handler: impl Into<AsyncEventHandler<T>>, handler: impl Into<AsyncEventHandler<T>>,
) -> EventHandlerRef<T> { ) -> EventHandlerRef<T> {
let handler = handler.into(); let handler = handler.into();
@ -133,7 +133,7 @@ pub async fn add_event_handler<T: Send + Sync + Copy + Sized + 'static>(
/// use simple_events::{Event, EventHandler}; /// use simple_events::{Event, EventHandler};
/// use simple_events::r#async::*; /// use simple_events::r#async::*;
/// ///
/// #[derive(Clone, Copy, Debug)] /// #[derive(Debug)]
/// struct Dummy; /// struct Dummy;
/// ///
/// async { /// async {
@ -152,10 +152,7 @@ pub async fn add_event_handler<T: Send + Sync + Copy + Sized + 'static>(
/// ///
/// ``` /// ```
/// ///
pub async fn remove_event_handler< pub async fn remove_event_handler<T: Send + Sync + Sized + 'static, F: Into<EventHandlerRef<T>>>(
T: Send + Sync + Copy + Sized + 'static,
F: Into<EventHandlerRef<T>>,
>(
handler_ref: F, handler_ref: F,
) { ) {
let mut map = HANDLER_MAP.write().await; let mut map = HANDLER_MAP.write().await;
@ -179,7 +176,7 @@ pub async fn remove_event_handler<
} }
} }
pub(crate) async fn dispatch_async<T: Send + Sync + Copy + Sized + 'static>( pub(crate) async fn dispatch_async<T: Send + Sync + Sized + 'static>(
event: impl Into<Event<T>>, event: impl Into<Event<T>>,
) -> Result<(), DispatchError> { ) -> Result<(), DispatchError> {
let map = HANDLER_MAP.read().await; let map = HANDLER_MAP.read().await;
@ -192,7 +189,7 @@ pub(crate) async fn dispatch_async<T: Send + Sync + Copy + Sized + 'static>(
let mut futures = JoinSet::new(); let mut futures = JoinSet::new();
handlers.iter().for_each(|handler| { handlers.iter().for_each(|handler| {
futures.spawn(handler.handle_event(event)); futures.spawn(handler.handle_event(event.clone()));
}); });
while let Some(res) = futures.join_next().await { while let Some(res) = futures.join_next().await {
@ -203,22 +200,23 @@ pub(crate) async fn dispatch_async<T: Send + Sync + Copy + Sized + 'static>(
Ok(()) Ok(())
} }
pub async fn dispatch<T: Send + Sync + Copy + Sized + 'static>( pub async fn dispatch<T: Send + Sync + Sized + 'static>(
event: impl Into<Event<T>>, event: impl Into<Event<T>>,
) -> Result<(), DispatchError> { ) -> Result<(), DispatchError> {
let event = event.into(); let event = event.into();
dispatch_async(*event).await?; dispatch_async::<T>(event.clone()).await?;
let pass_event = *event; let pass_event = event.clone();
let blocking_result = tokio::task::spawn_blocking(move || crate::dispatch_sync(pass_event)); let blocking_result =
tokio::task::spawn_blocking(move || crate::dispatch_sync::<T>(pass_event));
blocking_result.await.map_err(DispatchError::JoinError)?; blocking_result.await.map_err(DispatchError::JoinError)?;
Ok(()) Ok(())
} }
pub(crate) async fn dispatch_parallel_async<T: Send + Sync + Copy + Sized + 'static>( pub(crate) async fn dispatch_parallel_async<T: Send + Sync + Sized + 'static>(
event: impl Into<Event<T>>, event: impl Into<Event<T>>,
) -> Result<(), DispatchError> { ) -> Result<(), DispatchError> {
let map = HANDLER_MAP.read().await; let map = HANDLER_MAP.read().await;
@ -230,7 +228,7 @@ pub(crate) async fn dispatch_parallel_async<T: Send + Sync + Copy + Sized + 'sta
if let Some(handlers) = handlers { if let Some(handlers) = handlers {
let tasks = handlers let tasks = handlers
.iter() .iter()
.map(|handler| tokio::spawn(handler.handle_event(event))); .map(|handler| tokio::spawn(handler.handle_event(event.clone())));
for task in tasks { for task in tasks {
task.await.map_err(DispatchError::JoinError)?; task.await.map_err(DispatchError::JoinError)?;
@ -239,16 +237,15 @@ pub(crate) async fn dispatch_parallel_async<T: Send + Sync + Copy + Sized + 'sta
Ok(()) Ok(())
} }
pub async fn dispatch_parallel<T: Send + Sync + Copy + Sized + 'static>( pub async fn dispatch_parallel<T: Send + Sync + Sized + 'static>(
event: impl Into<Event<T>>, event: impl Into<Event<T>>,
) -> Result<(), DispatchError> { ) -> Result<(), DispatchError> {
let event = event.into(); let event = event.into();
dispatch_parallel_async(*event).await?; dispatch_parallel_async::<T>(event.clone()).await?;
let pass_event = *event;
let blocking_result = let blocking_result =
tokio::task::spawn_blocking(move || crate::dispatch_parallel_sync(pass_event)); tokio::task::spawn_blocking(move || crate::dispatch_parallel_sync::<T>(event.clone()));
blocking_result.await.map_err(DispatchError::JoinError)??; blocking_result.await.map_err(DispatchError::JoinError)??;
@ -263,7 +260,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn simple_closure() { async fn simple_closure() {
#[derive(Clone, Copy, Debug)] #[derive(Debug)]
struct Dummy { struct Dummy {
num: i32, num: i32,
} }
@ -295,7 +292,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn closure_plus_function() { async fn closure_plus_function() {
#[derive(Clone, Copy, Debug)] #[derive(Debug)]
struct Dummy; struct Dummy;
let call_count = Arc::new(Mutex::new(0)); let call_count = Arc::new(Mutex::new(0));
@ -336,7 +333,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn two_functions() { async fn two_functions() {
#[derive(Clone, Copy, Debug)] #[derive(Debug)]
struct Dummy; struct Dummy;
static CALL_COUNT: LazyLock<Mutex<i32>> = LazyLock::new(|| Mutex::new(0)); static CALL_COUNT: LazyLock<Mutex<i32>> = LazyLock::new(|| Mutex::new(0));
@ -361,7 +358,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn separate_closures() { async fn separate_closures() {
#[derive(Clone, Copy, Debug)] #[derive(Debug)]
struct Dummy; struct Dummy;
static CALL_COUNT: LazyLock<Mutex<i32>> = LazyLock::new(|| Mutex::new(0)); static CALL_COUNT: LazyLock<Mutex<i32>> = LazyLock::new(|| Mutex::new(0));

View file

@ -28,11 +28,11 @@ pub enum DispatchError {
struct KeyWrapper<T>(PhantomData<T>) struct KeyWrapper<T>(PhantomData<T>)
where where
T: Sized + Sync + Send + Copy; T: Sized + Sync + Send;
impl<T> Key for KeyWrapper<T> impl<T> Key for KeyWrapper<T>
where where
T: Send + Sync + Copy + Sized + 'static, T: Send + Sync + Sized + 'static,
{ {
type Value = Vec<Arc<EventHandler<T>>>; type Value = Vec<Arc<EventHandler<T>>>;
} }
@ -40,17 +40,28 @@ where
/// ///
/// A struct that wraps another struct so it can be dispatched via the event system. /// A struct that wraps another struct so it can be dispatched via the event system.
/// ///
#[derive(Copy, Clone, Debug)] #[derive(Debug)]
pub struct Event<T> pub struct Event<T>
where where
T: Sized + Send + Sync + Copy, T: Send + Sync + Sized,
{ {
inner: T, inner: Arc<T>,
}
impl<T> Clone for Event<T>
where
T: Send + Sync + Sized,
{
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
} }
impl<T> Deref for Event<T> impl<T> Deref for Event<T>
where where
T: Sized + Send + Sync + Copy, T: Sized + Send + Sync,
{ {
type Target = T; type Target = T;
@ -61,10 +72,12 @@ where
impl<T> Event<T> impl<T> Event<T>
where where
T: Sized + Send + Sync + Copy + 'static, T: Sized + Send + Sync + 'static,
{ {
pub fn new(inner: T) -> Self { pub fn new(inner: T) -> Self {
Self { inner } Self {
inner: Arc::new(inner),
}
} }
/// ///
@ -84,7 +97,7 @@ where
impl<T> From<T> for Event<T> impl<T> From<T> for Event<T>
where where
T: Sized + Send + Sync + Copy + 'static, T: Sized + Send + Sync + 'static,
{ {
fn from(value: T) -> Self { fn from(value: T) -> Self {
Self::new(value) Self::new(value)
@ -93,7 +106,7 @@ where
pub struct EventHandler<T> pub struct EventHandler<T>
where where
T: Sized + Send + Sync + Copy, T: Sized + Send + Sync,
{ {
handle_func: Box<dyn Fn(Event<T>) + Send + Sync>, handle_func: Box<dyn Fn(Event<T>) + Send + Sync>,
fn_id: TypeId, fn_id: TypeId,
@ -102,18 +115,18 @@ where
impl<T> PartialEq for EventHandler<T> impl<T> PartialEq for EventHandler<T>
where where
T: Sized + Send + Sync + Copy, T: Sized + Send + Sync,
{ {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.fn_id == other.fn_id self.fn_id == other.fn_id
} }
} }
impl<T> Eq for EventHandler<T> where T: Sized + Send + Sync + Copy {} impl<T> Eq for EventHandler<T> where T: Sized + Send + Sync {}
impl<T> EventHandler<T> impl<T> EventHandler<T>
where where
T: Send + Sync + Sized + Copy, T: Send + Sync + Sized,
{ {
fn handle_event(&self, event: Event<T>) { fn handle_event(&self, event: Event<T>) {
(self.handle_func)(event) (self.handle_func)(event)
@ -122,7 +135,7 @@ where
impl<T, F> From<F> for EventHandler<T> impl<T, F> From<F> for EventHandler<T>
where where
T: Send + Sync + Sized + Copy, T: Send + Sync + Sized,
F: (Fn(Event<T>)) + Send + Sync + 'static, F: (Fn(Event<T>)) + Send + Sync + 'static,
{ {
fn from(value: F) -> Self { fn from(value: F) -> Self {
@ -143,7 +156,7 @@ where
/// ```rust /// ```rust
/// use simple_events::*; /// use simple_events::*;
/// ///
/// #[derive(Clone, Copy, Debug)] /// #[derive(Debug)]
/// struct Dummy; /// struct Dummy;
/// ///
/// let closure = |_: Event<Dummy>| { /*...*/ }; /// let closure = |_: Event<Dummy>| { /*...*/ };
@ -162,7 +175,7 @@ pub struct EventHandlerRef<T> {
impl<T> From<&EventHandler<T>> for EventHandlerRef<T> impl<T> From<&EventHandler<T>> for EventHandlerRef<T>
where where
T: Send + Sync + Sized + Copy, T: Send + Sync + Sized,
{ {
fn from(value: &EventHandler<T>) -> Self { fn from(value: &EventHandler<T>) -> Self {
Self { Self {
@ -176,7 +189,7 @@ impl<F, T, R> From<F> for EventHandlerRef<T>
where where
R: Any, R: Any,
F: (Fn(Event<T>) -> R) + Send + Sync + 'static, F: (Fn(Event<T>) -> R) + Send + Sync + 'static,
T: Send + Sync + Copy + Sized, T: Send + Sync + Sized,
{ {
fn from(_: F) -> Self { fn from(_: F) -> Self {
Self { Self {
@ -195,7 +208,7 @@ where
/// ```rust /// ```rust
/// use simple_events::*; /// use simple_events::*;
/// ///
/// #[derive(Clone, Copy, Debug)] /// #[derive(Debug)]
/// struct Dummy; /// struct Dummy;
/// ///
/// // Removing a static function /// // Removing a static function
@ -212,10 +225,7 @@ where
/// ///
/// ``` /// ```
/// ///
pub fn remove_event_handler< pub fn remove_event_handler<T: Send + Sync + Sized + 'static, F: Into<EventHandlerRef<T>>>(
T: Send + Sync + Copy + Sized + 'static,
F: Into<EventHandlerRef<T>>,
>(
handler_ref: F, handler_ref: F,
) { ) {
let mut map = HANDLER_MAP.write(); let mut map = HANDLER_MAP.write();
@ -244,7 +254,7 @@ pub fn remove_event_handler<
/// parameter of type `Event<T>` where `T` is the type of event struct that it wants to /// parameter of type `Event<T>` where `T` is the type of event struct that it wants to
/// handle. /// handle.
/// ///
pub fn add_event_handler<T: Send + Sync + Copy + Sized + 'static>( pub fn add_event_handler<T: Send + Sync + Sized + 'static>(
handler: impl Into<EventHandler<T>>, handler: impl Into<EventHandler<T>>,
) -> EventHandlerRef<T> { ) -> EventHandlerRef<T> {
let handler = handler.into(); let handler = handler.into();
@ -271,7 +281,7 @@ pub fn add_event_handler<T: Send + Sync + Copy + Sized + 'static>(
/// ///
/// Although event handlers are called sequentially, the order of execution is _not_ guaranteed. /// Although event handlers are called sequentially, the order of execution is _not_ guaranteed.
/// ///
pub(crate) fn dispatch_sync<T: Send + Sync + Copy + Sized + 'static>(event: impl Into<Event<T>>) { pub(crate) fn dispatch_sync<T: Send + Sync + Sized + 'static>(event: impl Into<Event<T>>) {
let map = HANDLER_MAP.read(); let map = HANDLER_MAP.read();
let event = event.into(); let event = event.into();
@ -281,16 +291,16 @@ pub(crate) fn dispatch_sync<T: Send + Sync + Copy + Sized + 'static>(event: impl
if let Some(handlers) = handlers { if let Some(handlers) = handlers {
handlers handlers
.iter() .iter()
.for_each(|handler| handler.handle_event(event)) .for_each(|handler| handler.handle_event(event.clone()))
} }
} }
pub fn dispatch<T: Send + Sync + Copy + Sized + 'static>( pub fn dispatch<T: Send + Sync + Sized + 'static>(
event: impl Into<Event<T>>, event: impl Into<Event<T>>,
) -> Result<(), DispatchError> { ) -> Result<(), DispatchError> {
let event = event.into(); let event = event.into();
dispatch_sync(*event); dispatch_sync::<T>(event.clone());
#[cfg(feature = "tokio")] #[cfg(feature = "tokio")]
{ {
@ -310,7 +320,7 @@ pub fn dispatch<T: Send + Sync + Copy + Sized + 'static>(
/// ///
/// This function will return once all event handlers have finished executing. /// This function will return once all event handlers have finished executing.
/// ///
pub(crate) fn dispatch_parallel_sync<T: Send + Sync + Copy + Sized + 'static>( pub(crate) fn dispatch_parallel_sync<T: Send + Sync + Sized + 'static>(
event: impl Into<Event<T>>, event: impl Into<Event<T>>,
) -> Result<(), DispatchError> { ) -> Result<(), DispatchError> {
let map = HANDLER_MAP.read(); let map = HANDLER_MAP.read();
@ -324,6 +334,7 @@ pub(crate) fn dispatch_parallel_sync<T: Send + Sync + Copy + Sized + 'static>(
.iter() .iter()
.map(|handler| { .map(|handler| {
let handler = handler.clone(); let handler = handler.clone();
let event = event.clone();
thread::spawn(move || handler.handle_event(event)) thread::spawn(move || handler.handle_event(event))
}) })
.find_map(|r| if let Err(e) = r.join() { Some(e) } else { None }) .find_map(|r| if let Err(e) = r.join() { Some(e) } else { None })
@ -333,12 +344,12 @@ pub(crate) fn dispatch_parallel_sync<T: Send + Sync + Copy + Sized + 'static>(
Ok(()) Ok(())
} }
pub fn dispatch_parallel<T: Send + Sync + Copy + Sized + 'static>( pub fn dispatch_parallel<T: Send + Sync + Sized + 'static>(
event: impl Into<Event<T>>, event: impl Into<Event<T>>,
) -> Result<(), DispatchError> { ) -> Result<(), DispatchError> {
let event = event.into(); let event = event.into();
dispatch_parallel_sync(*event)?; dispatch_parallel_sync::<T>(event.clone())?;
#[cfg(feature = "tokio")] #[cfg(feature = "tokio")]
{ {
@ -362,7 +373,7 @@ mod tests {
#[test] #[test]
fn simple_closure() { fn simple_closure() {
#[derive(Clone, Copy, Debug)] #[derive(Debug)]
struct Dummy { struct Dummy {
num: i32, num: i32,
} }
@ -389,7 +400,7 @@ mod tests {
#[test] #[test]
fn closure_plus_function() { fn closure_plus_function() {
#[derive(Clone, Copy, Debug)] #[derive(Debug)]
struct Dummy; struct Dummy;
let call_count = Arc::new(Mutex::new(0)); let call_count = Arc::new(Mutex::new(0));
@ -424,7 +435,7 @@ mod tests {
#[test] #[test]
fn two_functions() { fn two_functions() {
#[derive(Clone, Copy, Debug)] #[derive(Debug)]
struct Dummy; struct Dummy;
static CALL_COUNT: Mutex<i32> = Mutex::new(0); static CALL_COUNT: Mutex<i32> = Mutex::new(0);
@ -449,7 +460,7 @@ mod tests {
#[test] #[test]
fn separate_closures() { fn separate_closures() {
#[derive(Clone, Copy, Debug)] #[derive(Debug)]
struct Dummy; struct Dummy;
static CALL_COUNT: Mutex<i32> = Mutex::new(0); static CALL_COUNT: Mutex<i32> = Mutex::new(0);