diff options
author | Alex Orlenko <zxteam@protonmail.com> | 2024-06-25 12:17:33 +0100 |
---|---|---|
committer | Alex Orlenko <zxteam@protonmail.com> | 2024-06-25 12:17:33 +0100 |
commit | 0a1f625f814a3bff8b3b092add0af0cd4817f611 (patch) | |
tree | f8bcf1a85dbe18231607897c3ebaf1e6b168db7a | |
parent | 6cd36cb50bd2602da0fac870c3016043c72f854d (diff) | |
download | mlua-0a1f625f814a3bff8b3b092add0af0cd4817f611.zip |
Optimize creation of userdata callbacks (registry)
-rw-r--r-- | src/userdata/cell.rs | 16 | ||||
-rw-r--r-- | src/userdata/registry.rs | 140 |
2 files changed, 81 insertions, 75 deletions
diff --git a/src/userdata/cell.rs b/src/userdata/cell.rs index 7205958..294b7b5 100644 --- a/src/userdata/cell.rs +++ b/src/userdata/cell.rs @@ -361,6 +361,14 @@ impl<'a, T> TryFrom<&'a UserDataVariant<T>> for UserDataBorrowRef<'a, T> { } } +impl<'a, T> UserDataBorrowRef<'a, T> { + #[inline(always)] + pub(crate) fn get_ref(&self) -> &'a T { + // SAFETY: `UserDataBorrowRef` is only created when the borrow flag is set to reading. + unsafe { self.0.get_ref() } + } +} + pub(crate) struct UserDataBorrowMut<'a, T>(&'a UserDataVariant<T>); impl<'a, T> Drop for UserDataBorrowMut<'a, T> { @@ -396,6 +404,14 @@ impl<'a, T> TryFrom<&'a UserDataVariant<T>> for UserDataBorrowMut<'a, T> { } } +impl<'a, T> UserDataBorrowMut<'a, T> { + #[inline(always)] + pub(crate) fn get_mut(&mut self) -> &'a mut T { + // SAFETY: `UserDataBorrowMut` is only created when the borrow flag is set to writing. + unsafe { self.0.get_mut() } + } +} + #[inline] fn try_value_to_userdata<T>(value: Value) -> Result<AnyUserData> { match value { diff --git a/src/userdata/registry.rs b/src/userdata/registry.rs index 3c92ca8..d0887cb 100644 --- a/src/userdata/registry.rs +++ b/src/userdata/registry.rs @@ -15,9 +15,6 @@ use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, Value}; use super::cell::{UserDataBorrowMut, UserDataBorrowRef, UserDataVariant}; -#[cfg(not(feature = "send"))] -use std::rc::Rc; - #[cfg(feature = "async")] use {crate::types::AsyncCallback, futures_util::future, std::future::Future}; @@ -68,9 +65,6 @@ impl<'a, T: 'static> UserDataRegistry<'a, T> { ($res:expr) => { $res.map_err(|err| Error::bad_self_argument(&name, err))? }; - ($res:expr, $err:expr) => { - $res.map_err(|_| Error::bad_self_argument(&name, $err))? - }; } Box::new(move |rawlua, nargs| unsafe { @@ -105,9 +99,6 @@ impl<'a, T: 'static> UserDataRegistry<'a, T> { ($res:expr) => { $res.map_err(|err| Error::bad_self_argument(&name, err))? }; - ($res:expr, $err:expr) => { - $res.map_err(|_| Error::bad_self_argument(&name, $err))? - }; } let method = RefCell::new(method); @@ -143,39 +134,40 @@ impl<'a, T: 'static> UserDataRegistry<'a, T> { MR: Future<Output = Result<R>> + 'a, R: IntoLuaMulti, { - let name = Rc::new(get_function_name::<T>(name)); - let method = Rc::new(method); + let name = get_function_name::<T>(name); + macro_rules! try_self_arg { + ($res:expr) => { + match $res { + Ok(res) => res, + Err(err) => return Box::pin(future::err(Error::bad_self_argument(&name, err))), + } + }; + } Box::new(move |rawlua, mut args| unsafe { - let name = name.clone(); - let method = method.clone(); - macro_rules! try_self_arg { - ($res:expr) => { - $res.map_err(|err| Error::bad_self_argument(&name, err))? - }; - ($res:expr, $err:expr) => { - $res.map_err(|_| Error::bad_self_argument(&name, $err))? - }; - } + let this = args + .pop_front() + .ok_or_else(|| Error::from_lua_conversion("missing argument", "userdata", None)); + let lua = rawlua.lua(); + let this = try_self_arg!(AnyUserData::from_lua(try_self_arg!(this), lua)); + let args = A::from_lua_args(args, 2, Some(&name), lua); - Box::pin(async move { - let this = args.pop_front().ok_or_else(|| { - Error::from_lua_conversion("missing argument", "userdata", None) - }); - let lua = rawlua.lua(); - let this = try_self_arg!(AnyUserData::from_lua(try_self_arg!(this), lua)); - let args = A::from_lua_args(args, 2, Some(&name), lua); - - let (ref_thread, index) = (rawlua.ref_thread(), this.0.index); - match try_self_arg!(this.type_id()) { - Some(id) if id == TypeId::of::<T>() => { - let ud = try_self_arg!(borrow_userdata_ref::<T>(ref_thread, index)); - let ud = std::mem::transmute::<&T, &T>(&ud); - method(lua, ud, args?).await?.push_into_stack_multi(&rawlua) - } - _ => Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch)), + let (ref_thread, index) = (rawlua.ref_thread(), this.0.index); + match try_self_arg!(this.type_id()) { + Some(id) if id == TypeId::of::<T>() => { + let ud = try_self_arg!(borrow_userdata_ref::<T>(ref_thread, index)); + let args = match args { + Ok(args) => args, + Err(e) => return Box::pin(future::err(e)), + }; + let fut = method(lua, ud.get_ref(), args); + Box::pin(async move { fut.await?.push_into_stack_multi(&rawlua) }) + } + _ => { + let err = Error::bad_self_argument(&name, Error::UserDataTypeMismatch); + Box::pin(future::err(err)) } - }) + } }) } @@ -187,39 +179,40 @@ impl<'a, T: 'static> UserDataRegistry<'a, T> { MR: Future<Output = Result<R>> + 'a, R: IntoLuaMulti, { - let name = Rc::new(get_function_name::<T>(name)); - let method = Rc::new(method); + let name = get_function_name::<T>(name); + macro_rules! try_self_arg { + ($res:expr) => { + match $res { + Ok(res) => res, + Err(err) => return Box::pin(future::err(Error::bad_self_argument(&name, err))), + } + }; + } Box::new(move |rawlua, mut args| unsafe { - let name = name.clone(); - let method = method.clone(); - macro_rules! try_self_arg { - ($res:expr) => { - $res.map_err(|err| Error::bad_self_argument(&name, err))? - }; - ($res:expr, $err:expr) => { - $res.map_err(|_| Error::bad_self_argument(&name, $err))? - }; - } + let this = args + .pop_front() + .ok_or_else(|| Error::from_lua_conversion("missing argument", "userdata", None)); + let lua = rawlua.lua(); + let this = try_self_arg!(AnyUserData::from_lua(try_self_arg!(this), lua)); + let args = A::from_lua_args(args, 2, Some(&name), lua); - Box::pin(async move { - let this = args.pop_front().ok_or_else(|| { - Error::from_lua_conversion("missing argument", "userdata", None) - }); - let lua = rawlua.lua(); - let this = try_self_arg!(AnyUserData::from_lua(try_self_arg!(this), lua)); - let args = A::from_lua_args(args, 2, Some(&name), lua); - - let (ref_thread, index) = (rawlua.ref_thread(), this.0.index); - match try_self_arg!(this.type_id()) { - Some(id) if id == TypeId::of::<T>() => { - let mut ud = try_self_arg!(borrow_userdata_mut::<T>(ref_thread, index)); - let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud); - method(lua, ud, args?).await?.push_into_stack_multi(&rawlua) - } - _ => Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch)), + let (ref_thread, index) = (rawlua.ref_thread(), this.0.index); + match try_self_arg!(this.type_id()) { + Some(id) if id == TypeId::of::<T>() => { + let mut ud = try_self_arg!(borrow_userdata_mut::<T>(ref_thread, index)); + let args = match args { + Ok(args) => args, + Err(e) => return Box::pin(future::err(e)), + }; + let fut = method(lua, ud.get_mut(), args); + Box::pin(async move { fut.await?.push_into_stack_multi(&rawlua) }) } - }) + _ => { + let err = Error::bad_self_argument(&name, Error::UserDataTypeMismatch); + Box::pin(future::err(err)) + } + } }) } @@ -269,8 +262,7 @@ impl<'a, T: 'static> UserDataRegistry<'a, T> { Err(e) => return Box::pin(future::err(e)), }; let fut = function(lua, args); - let weak = rawlua.weak().clone(); - Box::pin(async move { fut.await?.push_into_stack_multi(&weak.lock()) }) + Box::pin(async move { fut.await?.push_into_stack_multi(&rawlua) }) }) } @@ -356,11 +348,10 @@ impl<'a, T: 'static> UserDataFields<'a, T> for UserDataRegistry<'a, T> { V: IntoLua + Clone + 'static, { let name = name.to_string(); - let name2 = name.clone(); self.meta_fields.push(( - name, + name.clone(), Box::new(move |lua, _| unsafe { - Self::check_meta_field(lua.lua(), &name2, value.clone())?.push_into_stack_multi(lua) + Self::check_meta_field(lua.lua(), &name, value.clone())?.push_into_stack_multi(lua) }), )); } @@ -371,12 +362,11 @@ impl<'a, T: 'static> UserDataFields<'a, T> for UserDataRegistry<'a, T> { R: IntoLua, { let name = name.to_string(); - let name2 = name.clone(); self.meta_fields.push(( - name, + name.clone(), Box::new(move |rawlua, _| unsafe { let lua = rawlua.lua(); - Self::check_meta_field(lua, &name2, f(lua)?)?.push_into_stack_multi(rawlua) + Self::check_meta_field(lua, &name, f(lua)?)?.push_into_stack_multi(rawlua) }), )); } |