From 7a75c7305227d31c941a002006da684b28806b5b Mon Sep 17 00:00:00 2001 From: Alex Orlenko Date: Mon, 8 Jul 2024 23:10:28 +0100 Subject: [PATCH] Move `AppData` to `types::app_data` mod --- src/types.rs | 165 ++------------------------------------ src/types/app_data.rs | 180 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+), 159 deletions(-) create mode 100644 src/types/app_data.rs diff --git a/src/types.rs b/src/types.rs index dc91cc1a..abd88af2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,21 +1,17 @@ -use std::any::{Any, TypeId}; -use std::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell}; +use std::cell::UnsafeCell; use std::hash::{Hash, Hasher}; -use std::ops::{Deref, DerefMut}; use std::os::raw::{c_int, c_void}; use std::rc::Rc; -use std::result::Result as StdResult; use std::sync::atomic::{AtomicI32, Ordering}; use std::sync::Arc; use std::{fmt, mem, ptr}; use parking_lot::Mutex; -use rustc_hash::FxHashMap; use crate::error::Result; #[cfg(not(feature = "luau"))] use crate::hook::Debug; -use crate::state::{ExtraData, Lua, LuaGuard, RawLua, WeakLua}; +use crate::state::{ExtraData, Lua, RawLua, WeakLua}; #[cfg(feature = "async")] use {crate::value::MultiValue, futures_util::future::LocalBoxFuture}; @@ -24,6 +20,7 @@ use {crate::value::MultiValue, futures_util::future::LocalBoxFuture}; use serde::ser::{Serialize, SerializeTupleStruct, Serializer}; // Re-export mutex wrappers +pub use app_data::{AppData, AppDataRef, AppDataRefMut}; pub(crate) use sync::{ArcReentrantMutexGuard, ReentrantMutex, ReentrantMutexGuard, XRc, XWeak}; /// Type of Lua integer numbers. @@ -49,7 +46,7 @@ pub(crate) type Callback<'a> = Box Result + pub(crate) struct Upvalue { pub(crate) data: T, - pub(crate) extra: Rc>, + pub(crate) extra: XRc>, } pub(crate) type CallbackUpvalue = Upvalue>; @@ -167,7 +164,7 @@ impl Vector { #[cfg(all(feature = "luau", feature = "serialize"))] impl Serialize for Vector { - fn serialize(&self, serializer: S) -> StdResult { + fn serialize(&self, serializer: S) -> std::result::Result { let mut ts = serializer.serialize_tuple_struct("Vector", Self::SIZE)?; ts.serialize_field(&self.x())?; ts.serialize_field(&self.y())?; @@ -331,157 +328,7 @@ impl PartialEq for ValueRef { } } -#[derive(Debug, Default)] -pub(crate) struct AppData { - #[cfg(not(feature = "send"))] - container: UnsafeCell>>>, - #[cfg(feature = "send")] - container: UnsafeCell>>>, - borrow: Cell, -} - -impl AppData { - #[track_caller] - pub(crate) fn insert(&self, data: T) -> Option { - match self.try_insert(data) { - Ok(data) => data, - Err(_) => panic!("cannot mutably borrow app data container"), - } - } - - pub(crate) fn try_insert(&self, data: T) -> StdResult, T> { - if self.borrow.get() != 0 { - return Err(data); - } - // SAFETY: we checked that there are no other references to the container - Ok(unsafe { &mut *self.container.get() } - .insert(TypeId::of::(), RefCell::new(Box::new(data))) - .and_then(|data| data.into_inner().downcast::().ok().map(|data| *data))) - } - - #[track_caller] - pub(crate) fn borrow(&self, guard: Option) -> Option> { - let data = unsafe { &*self.container.get() } - .get(&TypeId::of::())? - .borrow(); - self.borrow.set(self.borrow.get() + 1); - Some(AppDataRef { - data: Ref::filter_map(data, |data| data.downcast_ref()).ok()?, - borrow: &self.borrow, - _guard: guard, - }) - } - - #[track_caller] - pub(crate) fn borrow_mut( - &self, - guard: Option, - ) -> Option> { - let data = unsafe { &*self.container.get() } - .get(&TypeId::of::())? - .borrow_mut(); - self.borrow.set(self.borrow.get() + 1); - Some(AppDataRefMut { - data: RefMut::filter_map(data, |data| data.downcast_mut()).ok()?, - borrow: &self.borrow, - _guard: guard, - }) - } - - #[track_caller] - pub(crate) fn remove(&self) -> Option { - if self.borrow.get() != 0 { - panic!("cannot mutably borrow app data container"); - } - // SAFETY: we checked that there are no other references to the container - unsafe { &mut *self.container.get() } - .remove(&TypeId::of::())? - .into_inner() - .downcast::() - .ok() - .map(|data| *data) - } -} - -/// A wrapper type for an immutably borrowed value from an app data container. -/// -/// This type is similar to [`Ref`]. -pub struct AppDataRef<'a, T: ?Sized + 'a> { - data: Ref<'a, T>, - borrow: &'a Cell, - _guard: Option, -} - -impl Drop for AppDataRef<'_, T> { - fn drop(&mut self) { - self.borrow.set(self.borrow.get() - 1); - } -} - -impl Deref for AppDataRef<'_, T> { - type Target = T; - - #[inline] - fn deref(&self) -> &Self::Target { - &self.data - } -} - -impl fmt::Display for AppDataRef<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -impl fmt::Debug for AppDataRef<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -/// A wrapper type for a mutably borrowed value from an app data container. -/// -/// This type is similar to [`RefMut`]. -pub struct AppDataRefMut<'a, T: ?Sized + 'a> { - data: RefMut<'a, T>, - borrow: &'a Cell, - _guard: Option, -} - -impl Drop for AppDataRefMut<'_, T> { - fn drop(&mut self) { - self.borrow.set(self.borrow.get() - 1); - } -} - -impl Deref for AppDataRefMut<'_, T> { - type Target = T; - - #[inline] - fn deref(&self) -> &Self::Target { - &self.data - } -} - -impl DerefMut for AppDataRefMut<'_, T> { - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.data - } -} - -impl fmt::Display for AppDataRefMut<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -impl fmt::Debug for AppDataRefMut<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - +mod app_data; mod sync; #[cfg(test)] diff --git a/src/types/app_data.rs b/src/types/app_data.rs new file mode 100644 index 00000000..3b6a4ab0 --- /dev/null +++ b/src/types/app_data.rs @@ -0,0 +1,180 @@ +use std::any::{Any, TypeId}; +use std::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell}; +use std::fmt; +use std::ops::{Deref, DerefMut}; +use std::result::Result as StdResult; + +use rustc_hash::FxHashMap; + +use crate::state::LuaGuard; + +use super::MaybeSend; + +#[cfg(not(feature = "send"))] +type Container = UnsafeCell>>>; + +#[cfg(feature = "send")] +type Container = UnsafeCell>>>; + +/// A container for arbitrary data associated with the Lua state. +#[derive(Debug, Default)] +pub struct AppData { + container: Container, + borrow: Cell, +} + +impl AppData { + #[track_caller] + pub(crate) fn insert(&self, data: T) -> Option { + match self.try_insert(data) { + Ok(data) => data, + Err(_) => panic!("cannot mutably borrow app data container"), + } + } + + pub(crate) fn try_insert(&self, data: T) -> StdResult, T> { + if self.borrow.get() != 0 { + return Err(data); + } + // SAFETY: we checked that there are no other references to the container + Ok(unsafe { &mut *self.container.get() } + .insert(TypeId::of::(), RefCell::new(Box::new(data))) + .and_then(|data| data.into_inner().downcast::().ok().map(|data| *data))) + } + + #[track_caller] + pub(crate) fn borrow(&self, guard: Option) -> Option> { + let data = unsafe { &*self.container.get() } + .get(&TypeId::of::())? + .borrow(); + self.borrow.set(self.borrow.get() + 1); + Some(AppDataRef { + data: Ref::filter_map(data, |data| data.downcast_ref()).ok()?, + borrow: &self.borrow, + _guard: guard, + }) + } + + #[track_caller] + pub(crate) fn borrow_mut( + &self, + guard: Option, + ) -> Option> { + let data = unsafe { &*self.container.get() } + .get(&TypeId::of::())? + .borrow_mut(); + self.borrow.set(self.borrow.get() + 1); + Some(AppDataRefMut { + data: RefMut::filter_map(data, |data| data.downcast_mut()).ok()?, + borrow: &self.borrow, + _guard: guard, + }) + } + + #[track_caller] + pub(crate) fn remove(&self) -> Option { + if self.borrow.get() != 0 { + panic!("cannot mutably borrow app data container"); + } + // SAFETY: we checked that there are no other references to the container + unsafe { &mut *self.container.get() } + .remove(&TypeId::of::())? + .into_inner() + .downcast::() + .ok() + .map(|data| *data) + } +} + +/// A wrapper type for an immutably borrowed value from an app data container. +/// +/// This type is similar to [`Ref`]. +pub struct AppDataRef<'a, T: ?Sized + 'a> { + data: Ref<'a, T>, + borrow: &'a Cell, + _guard: Option, +} + +impl Drop for AppDataRef<'_, T> { + fn drop(&mut self) { + self.borrow.set(self.borrow.get() - 1); + } +} + +impl Deref for AppDataRef<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.data + } +} + +impl fmt::Display for AppDataRef<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + +impl fmt::Debug for AppDataRef<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + +/// A wrapper type for a mutably borrowed value from an app data container. +/// +/// This type is similar to [`RefMut`]. +pub struct AppDataRefMut<'a, T: ?Sized + 'a> { + data: RefMut<'a, T>, + borrow: &'a Cell, + _guard: Option, +} + +impl Drop for AppDataRefMut<'_, T> { + fn drop(&mut self) { + self.borrow.set(self.borrow.get() - 1); + } +} + +impl Deref for AppDataRefMut<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.data + } +} + +impl DerefMut for AppDataRefMut<'_, T> { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.data + } +} + +impl fmt::Display for AppDataRefMut<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + +impl fmt::Debug for AppDataRefMut<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + +#[cfg(test)] +mod assertions { + use super::*; + + #[cfg(not(feature = "send"))] + static_assertions::assert_not_impl_any!(AppData: Send); + #[cfg(feature = "send")] + static_assertions::assert_impl_all!(AppData: Send); + + // Must be !Send + static_assertions::assert_not_impl_any!(AppDataRef<()>: Send); + static_assertions::assert_not_impl_any!(AppDataRefMut<()>: Send); +}