Skip to content

Commit ccedb22

Browse files
committed
Move AppData to types::app_data mod
1 parent eabb857 commit ccedb22

File tree

2 files changed

+185
-158
lines changed

2 files changed

+185
-158
lines changed

src/types.rs

Lines changed: 5 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
1-
use std::any::{Any, TypeId};
2-
use std::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell};
1+
use std::cell::UnsafeCell;
32
use std::hash::{Hash, Hasher};
4-
use std::ops::{Deref, DerefMut};
53
use std::os::raw::{c_int, c_void};
64
use std::rc::Rc;
7-
use std::result::Result as StdResult;
85
use std::sync::atomic::{AtomicI32, Ordering};
96
use std::sync::Arc;
107
use std::{fmt, mem, ptr};
118

129
use parking_lot::Mutex;
13-
use rustc_hash::FxHashMap;
1410

1511
use crate::error::Result;
1612
#[cfg(not(feature = "luau"))]
1713
use crate::hook::Debug;
18-
use crate::state::{ExtraData, Lua, LuaGuard, RawLua, WeakLua};
14+
use crate::state::{ExtraData, Lua, RawLua, WeakLua};
1915

2016
#[cfg(feature = "async")]
2117
use {crate::value::MultiValue, futures_util::future::LocalBoxFuture};
@@ -24,6 +20,7 @@ use {crate::value::MultiValue, futures_util::future::LocalBoxFuture};
2420
use serde::ser::{Serialize, SerializeTupleStruct, Serializer};
2521

2622
// Re-export mutex wrappers
23+
pub use app_data::{AppData, AppDataRef, AppDataRefMut};
2724
pub(crate) use sync::{ArcReentrantMutexGuard, ReentrantMutex, ReentrantMutexGuard, XRc, XWeak};
2825

2926
/// Type of Lua integer numbers.
@@ -49,7 +46,7 @@ pub(crate) type Callback<'a> = Box<dyn Fn(&'a RawLua, c_int) -> Result<c_int> +
4946

5047
pub(crate) struct Upvalue<T> {
5148
pub(crate) data: T,
52-
pub(crate) extra: Rc<UnsafeCell<ExtraData>>,
49+
pub(crate) extra: XRc<UnsafeCell<ExtraData>>,
5350
}
5451

5552
pub(crate) type CallbackUpvalue = Upvalue<Callback<'static>>;
@@ -331,157 +328,7 @@ impl PartialEq for ValueRef {
331328
}
332329
}
333330

334-
#[derive(Debug, Default)]
335-
pub(crate) struct AppData {
336-
#[cfg(not(feature = "send"))]
337-
container: UnsafeCell<FxHashMap<TypeId, RefCell<Box<dyn Any>>>>,
338-
#[cfg(feature = "send")]
339-
container: UnsafeCell<FxHashMap<TypeId, RefCell<Box<dyn Any + Send>>>>,
340-
borrow: Cell<usize>,
341-
}
342-
343-
impl AppData {
344-
#[track_caller]
345-
pub(crate) fn insert<T: MaybeSend + 'static>(&self, data: T) -> Option<T> {
346-
match self.try_insert(data) {
347-
Ok(data) => data,
348-
Err(_) => panic!("cannot mutably borrow app data container"),
349-
}
350-
}
351-
352-
pub(crate) fn try_insert<T: MaybeSend + 'static>(&self, data: T) -> StdResult<Option<T>, T> {
353-
if self.borrow.get() != 0 {
354-
return Err(data);
355-
}
356-
// SAFETY: we checked that there are no other references to the container
357-
Ok(unsafe { &mut *self.container.get() }
358-
.insert(TypeId::of::<T>(), RefCell::new(Box::new(data)))
359-
.and_then(|data| data.into_inner().downcast::<T>().ok().map(|data| *data)))
360-
}
361-
362-
#[track_caller]
363-
pub(crate) fn borrow<T: 'static>(&self, guard: Option<LuaGuard>) -> Option<AppDataRef<T>> {
364-
let data = unsafe { &*self.container.get() }
365-
.get(&TypeId::of::<T>())?
366-
.borrow();
367-
self.borrow.set(self.borrow.get() + 1);
368-
Some(AppDataRef {
369-
data: Ref::filter_map(data, |data| data.downcast_ref()).ok()?,
370-
borrow: &self.borrow,
371-
_guard: guard,
372-
})
373-
}
374-
375-
#[track_caller]
376-
pub(crate) fn borrow_mut<T: 'static>(
377-
&self,
378-
guard: Option<LuaGuard>,
379-
) -> Option<AppDataRefMut<T>> {
380-
let data = unsafe { &*self.container.get() }
381-
.get(&TypeId::of::<T>())?
382-
.borrow_mut();
383-
self.borrow.set(self.borrow.get() + 1);
384-
Some(AppDataRefMut {
385-
data: RefMut::filter_map(data, |data| data.downcast_mut()).ok()?,
386-
borrow: &self.borrow,
387-
_guard: guard,
388-
})
389-
}
390-
391-
#[track_caller]
392-
pub(crate) fn remove<T: 'static>(&self) -> Option<T> {
393-
if self.borrow.get() != 0 {
394-
panic!("cannot mutably borrow app data container");
395-
}
396-
// SAFETY: we checked that there are no other references to the container
397-
unsafe { &mut *self.container.get() }
398-
.remove(&TypeId::of::<T>())?
399-
.into_inner()
400-
.downcast::<T>()
401-
.ok()
402-
.map(|data| *data)
403-
}
404-
}
405-
406-
/// A wrapper type for an immutably borrowed value from an app data container.
407-
///
408-
/// This type is similar to [`Ref`].
409-
pub struct AppDataRef<'a, T: ?Sized + 'a> {
410-
data: Ref<'a, T>,
411-
borrow: &'a Cell<usize>,
412-
_guard: Option<LuaGuard>,
413-
}
414-
415-
impl<T: ?Sized> Drop for AppDataRef<'_, T> {
416-
fn drop(&mut self) {
417-
self.borrow.set(self.borrow.get() - 1);
418-
}
419-
}
420-
421-
impl<T: ?Sized> Deref for AppDataRef<'_, T> {
422-
type Target = T;
423-
424-
#[inline]
425-
fn deref(&self) -> &Self::Target {
426-
&self.data
427-
}
428-
}
429-
430-
impl<T: ?Sized + fmt::Display> fmt::Display for AppDataRef<'_, T> {
431-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
432-
(**self).fmt(f)
433-
}
434-
}
435-
436-
impl<T: ?Sized + fmt::Debug> fmt::Debug for AppDataRef<'_, T> {
437-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
438-
(**self).fmt(f)
439-
}
440-
}
441-
442-
/// A wrapper type for a mutably borrowed value from an app data container.
443-
///
444-
/// This type is similar to [`RefMut`].
445-
pub struct AppDataRefMut<'a, T: ?Sized + 'a> {
446-
data: RefMut<'a, T>,
447-
borrow: &'a Cell<usize>,
448-
_guard: Option<LuaGuard>,
449-
}
450-
451-
impl<T: ?Sized> Drop for AppDataRefMut<'_, T> {
452-
fn drop(&mut self) {
453-
self.borrow.set(self.borrow.get() - 1);
454-
}
455-
}
456-
457-
impl<T: ?Sized> Deref for AppDataRefMut<'_, T> {
458-
type Target = T;
459-
460-
#[inline]
461-
fn deref(&self) -> &Self::Target {
462-
&self.data
463-
}
464-
}
465-
466-
impl<T: ?Sized> DerefMut for AppDataRefMut<'_, T> {
467-
#[inline]
468-
fn deref_mut(&mut self) -> &mut Self::Target {
469-
&mut self.data
470-
}
471-
}
472-
473-
impl<T: ?Sized + fmt::Display> fmt::Display for AppDataRefMut<'_, T> {
474-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
475-
(**self).fmt(f)
476-
}
477-
}
478-
479-
impl<T: ?Sized + fmt::Debug> fmt::Debug for AppDataRefMut<'_, T> {
480-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
481-
(**self).fmt(f)
482-
}
483-
}
484-
331+
mod app_data;
485332
mod sync;
486333

487334
#[cfg(test)]

src/types/app_data.rs

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
use std::any::{Any, TypeId};
2+
use std::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell};
3+
use std::fmt;
4+
use std::ops::{Deref, DerefMut};
5+
use std::result::Result as StdResult;
6+
7+
use rustc_hash::FxHashMap;
8+
9+
use crate::state::LuaGuard;
10+
11+
use super::MaybeSend;
12+
13+
#[cfg(not(feature = "send"))]
14+
type Container = UnsafeCell<FxHashMap<TypeId, RefCell<Box<dyn Any>>>>;
15+
16+
#[cfg(feature = "send")]
17+
type Container = UnsafeCell<FxHashMap<TypeId, RefCell<Box<dyn Any + Send>>>>;
18+
19+
/// A container for arbitrary data associated with the Lua state.
20+
#[derive(Debug, Default)]
21+
pub struct AppData {
22+
container: Container,
23+
borrow: Cell<usize>,
24+
}
25+
26+
impl AppData {
27+
#[track_caller]
28+
pub(crate) fn insert<T: MaybeSend + 'static>(&self, data: T) -> Option<T> {
29+
match self.try_insert(data) {
30+
Ok(data) => data,
31+
Err(_) => panic!("cannot mutably borrow app data container"),
32+
}
33+
}
34+
35+
pub(crate) fn try_insert<T: MaybeSend + 'static>(&self, data: T) -> StdResult<Option<T>, T> {
36+
if self.borrow.get() != 0 {
37+
return Err(data);
38+
}
39+
// SAFETY: we checked that there are no other references to the container
40+
Ok(unsafe { &mut *self.container.get() }
41+
.insert(TypeId::of::<T>(), RefCell::new(Box::new(data)))
42+
.and_then(|data| data.into_inner().downcast::<T>().ok().map(|data| *data)))
43+
}
44+
45+
#[track_caller]
46+
pub(crate) fn borrow<T: 'static>(&self, guard: Option<LuaGuard>) -> Option<AppDataRef<T>> {
47+
let data = unsafe { &*self.container.get() }
48+
.get(&TypeId::of::<T>())?
49+
.borrow();
50+
self.borrow.set(self.borrow.get() + 1);
51+
Some(AppDataRef {
52+
data: Ref::filter_map(data, |data| data.downcast_ref()).ok()?,
53+
borrow: &self.borrow,
54+
_guard: guard,
55+
})
56+
}
57+
58+
#[track_caller]
59+
pub(crate) fn borrow_mut<T: 'static>(
60+
&self,
61+
guard: Option<LuaGuard>,
62+
) -> Option<AppDataRefMut<T>> {
63+
let data = unsafe { &*self.container.get() }
64+
.get(&TypeId::of::<T>())?
65+
.borrow_mut();
66+
self.borrow.set(self.borrow.get() + 1);
67+
Some(AppDataRefMut {
68+
data: RefMut::filter_map(data, |data| data.downcast_mut()).ok()?,
69+
borrow: &self.borrow,
70+
_guard: guard,
71+
})
72+
}
73+
74+
#[track_caller]
75+
pub(crate) fn remove<T: 'static>(&self) -> Option<T> {
76+
if self.borrow.get() != 0 {
77+
panic!("cannot mutably borrow app data container");
78+
}
79+
// SAFETY: we checked that there are no other references to the container
80+
unsafe { &mut *self.container.get() }
81+
.remove(&TypeId::of::<T>())?
82+
.into_inner()
83+
.downcast::<T>()
84+
.ok()
85+
.map(|data| *data)
86+
}
87+
}
88+
89+
/// A wrapper type for an immutably borrowed value from an app data container.
90+
///
91+
/// This type is similar to [`Ref`].
92+
pub struct AppDataRef<'a, T: ?Sized + 'a> {
93+
data: Ref<'a, T>,
94+
borrow: &'a Cell<usize>,
95+
_guard: Option<LuaGuard>,
96+
}
97+
98+
impl<T: ?Sized> Drop for AppDataRef<'_, T> {
99+
fn drop(&mut self) {
100+
self.borrow.set(self.borrow.get() - 1);
101+
}
102+
}
103+
104+
impl<T: ?Sized> Deref for AppDataRef<'_, T> {
105+
type Target = T;
106+
107+
#[inline]
108+
fn deref(&self) -> &Self::Target {
109+
&self.data
110+
}
111+
}
112+
113+
impl<T: ?Sized + fmt::Display> fmt::Display for AppDataRef<'_, T> {
114+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115+
(**self).fmt(f)
116+
}
117+
}
118+
119+
impl<T: ?Sized + fmt::Debug> fmt::Debug for AppDataRef<'_, T> {
120+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121+
(**self).fmt(f)
122+
}
123+
}
124+
125+
/// A wrapper type for a mutably borrowed value from an app data container.
126+
///
127+
/// This type is similar to [`RefMut`].
128+
pub struct AppDataRefMut<'a, T: ?Sized + 'a> {
129+
data: RefMut<'a, T>,
130+
borrow: &'a Cell<usize>,
131+
_guard: Option<LuaGuard>,
132+
}
133+
134+
impl<T: ?Sized> Drop for AppDataRefMut<'_, T> {
135+
fn drop(&mut self) {
136+
self.borrow.set(self.borrow.get() - 1);
137+
}
138+
}
139+
140+
impl<T: ?Sized> Deref for AppDataRefMut<'_, T> {
141+
type Target = T;
142+
143+
#[inline]
144+
fn deref(&self) -> &Self::Target {
145+
&self.data
146+
}
147+
}
148+
149+
impl<T: ?Sized> DerefMut for AppDataRefMut<'_, T> {
150+
#[inline]
151+
fn deref_mut(&mut self) -> &mut Self::Target {
152+
&mut self.data
153+
}
154+
}
155+
156+
impl<T: ?Sized + fmt::Display> fmt::Display for AppDataRefMut<'_, T> {
157+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158+
(**self).fmt(f)
159+
}
160+
}
161+
162+
impl<T: ?Sized + fmt::Debug> fmt::Debug for AppDataRefMut<'_, T> {
163+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164+
(**self).fmt(f)
165+
}
166+
}
167+
168+
#[cfg(test)]
169+
mod assertions {
170+
use super::*;
171+
172+
#[cfg(not(feature = "send"))]
173+
static_assertions::assert_not_impl_any!(AppData: Send);
174+
#[cfg(feature = "send")]
175+
static_assertions::assert_impl_all!(AppData: Send);
176+
177+
// Must be !Send
178+
static_assertions::assert_not_impl_any!(AppDataRef<()>: Send);
179+
static_assertions::assert_not_impl_any!(AppDataRefMut<()>: Send);
180+
}

0 commit comments

Comments
 (0)