diff options
author | Alex Orlenko <zxteam@protonmail.com> | 2021-04-27 18:31:57 +0100 |
---|---|---|
committer | Alex Orlenko <zxteam@protonmail.com> | 2021-04-27 21:55:31 +0100 |
commit | 463fc646bc8c5ecccbbd08fa8c3b8557903daebd (patch) | |
tree | 150d239a52b6c735d1a86c72ef8e7197614b7d2f /src/userdata.rs | |
parent | b5f1325f2f18756225ba9c94f023fb54807812eb (diff) | |
download | mlua-463fc646bc8c5ecccbbd08fa8c3b8557903daebd.zip |
Refactor UserDataCell
Diffstat (limited to 'src/userdata.rs')
-rw-r--r-- | src/userdata.rs | 75 |
1 files changed, 55 insertions, 20 deletions
diff --git a/src/userdata.rs b/src/userdata.rs index f823a0b..f097130 100644 --- a/src/userdata.rs +++ b/src/userdata.rs @@ -1,7 +1,9 @@ -use std::cell::{Ref, RefMut}; +use std::cell::{Ref, RefCell, RefMut}; use std::fmt; use std::hash::{Hash, Hasher}; +use std::ops::Deref; use std::string::String as StdString; +use std::sync::Arc; #[cfg(feature = "async")] use std::future::Future; @@ -17,7 +19,7 @@ use crate::ffi; use crate::function::Function; use crate::lua::Lua; use crate::table::{Table, TablePairs}; -use crate::types::{Integer, LuaRef, MaybeSend, UserDataCell}; +use crate::types::{Integer, LuaRef, MaybeSend}; use crate::util::{assert_stack, get_destructed_userdata_metatable, get_userdata, StackGuard}; use crate::value::{FromLua, FromLuaMulti, ToLua, ToLuaMulti, Value}; @@ -544,31 +546,26 @@ pub trait UserData: Sized { fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(_methods: &mut M) {} } -pub(crate) struct UserDataWrapped<T> { - pub(crate) data: *mut T, - #[cfg(feature = "serialize")] - ser: *mut dyn erased_serde::Serialize, +pub(crate) enum UserDataCell<T> { + Arc(Arc<RefCell<UserDataWrapped<T>>>), + Plain(RefCell<UserDataWrapped<T>>), } -impl<T> Drop for UserDataWrapped<T> { - fn drop(&mut self) { - unsafe { - drop(Box::from_raw(self.data)); +impl<T> UserDataCell<T> { + pub(crate) fn new(data: T) -> Self { + UserDataCell::Plain(RefCell::new(UserDataWrapped { + data: Box::into_raw(Box::new(data)), #[cfg(feature = "serialize")] - if self.data as *mut () != self.ser as *mut () { - drop(Box::from_raw(self.ser)); - } - } + ser: Box::into_raw(Box::new(UserDataSerializeError)), + })) } -} -impl<T> UserDataWrapped<T> { - pub(crate) fn new(data: T) -> Self { - UserDataWrapped { + pub(crate) fn new_arc(data: T) -> Self { + UserDataCell::Arc(Arc::new(RefCell::new(UserDataWrapped { data: Box::into_raw(Box::new(data)), #[cfg(feature = "serialize")] ser: Box::into_raw(Box::new(UserDataSerializeError)), - } + }))) } #[cfg(feature = "serialize")] @@ -577,9 +574,47 @@ impl<T> UserDataWrapped<T> { T: 'static + Serialize, { let data_raw = Box::into_raw(Box::new(data)); - UserDataWrapped { + UserDataCell::Plain(RefCell::new(UserDataWrapped { data: data_raw, ser: data_raw, + })) + } +} + +impl<T> Deref for UserDataCell<T> { + type Target = RefCell<UserDataWrapped<T>>; + + fn deref(&self) -> &Self::Target { + match self { + UserDataCell::Arc(t) => &*t, + UserDataCell::Plain(t) => &*t, + } + } +} + +impl<T> Clone for UserDataCell<T> { + fn clone(&self) -> Self { + match self { + UserDataCell::Arc(t) => UserDataCell::Arc(t.clone()), + UserDataCell::Plain(_) => mlua_panic!("cannot clone plain userdata"), + } + } +} + +pub(crate) struct UserDataWrapped<T> { + pub(crate) data: *mut T, + #[cfg(feature = "serialize")] + ser: *mut dyn erased_serde::Serialize, +} + +impl<T> Drop for UserDataWrapped<T> { + fn drop(&mut self) { + unsafe { + drop(Box::from_raw(self.data)); + #[cfg(feature = "serialize")] + if self.data as *mut () != self.ser as *mut () { + drop(Box::from_raw(self.ser)); + } } } } |