summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Orlenko <zxteam@protonmail.com>2024-06-25 12:17:33 +0100
committerAlex Orlenko <zxteam@protonmail.com>2024-06-25 12:17:33 +0100
commit0a1f625f814a3bff8b3b092add0af0cd4817f611 (patch)
treef8bcf1a85dbe18231607897c3ebaf1e6b168db7a
parent6cd36cb50bd2602da0fac870c3016043c72f854d (diff)
downloadmlua-0a1f625f814a3bff8b3b092add0af0cd4817f611.zip
Optimize creation of userdata callbacks (registry)
-rw-r--r--src/userdata/cell.rs16
-rw-r--r--src/userdata/registry.rs140
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)
}),
));
}