summaryrefslogtreecommitdiff
path: root/src/userdata.rs
diff options
context:
space:
mode:
authorAlex Orlenko <zxteam@protonmail.com>2021-04-27 18:31:57 +0100
committerAlex Orlenko <zxteam@protonmail.com>2021-04-27 21:55:31 +0100
commit463fc646bc8c5ecccbbd08fa8c3b8557903daebd (patch)
tree150d239a52b6c735d1a86c72ef8e7197614b7d2f /src/userdata.rs
parentb5f1325f2f18756225ba9c94f023fb54807812eb (diff)
downloadmlua-463fc646bc8c5ecccbbd08fa8c3b8557903daebd.zip
Refactor UserDataCell
Diffstat (limited to 'src/userdata.rs')
-rw-r--r--src/userdata.rs75
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));
+ }
}
}
}