Skip to content

Commit ae7cdcb

Browse files
committed
Remove (internal) borrow counter and use instead "locked" flag and strong reference counter
1 parent dacddfa commit ae7cdcb

File tree

4 files changed

+28
-19
lines changed

4 files changed

+28
-19
lines changed

src/userdata/cell.rs

+14-16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::any::{type_name, TypeId};
2-
use std::cell::{Cell, RefCell, UnsafeCell};
2+
use std::cell::{RefCell, UnsafeCell};
33
use std::fmt;
44
use std::ops::{Deref, DerefMut};
55
use std::os::raw::c_int;
@@ -91,20 +91,20 @@ impl<T> UserDataVariant<T> {
9191
}
9292

9393
#[inline(always)]
94-
fn raw_lock(&self) -> &RawLock {
94+
fn strong_count(&self) -> usize {
9595
match self {
96-
Self::Default(inner) => &inner.raw_lock,
96+
Self::Default(inner) => XRc::strong_count(inner),
9797
#[cfg(feature = "serialize")]
98-
Self::Serializable(inner) => &inner.raw_lock,
98+
Self::Serializable(inner) => XRc::strong_count(inner),
9999
}
100100
}
101101

102102
#[inline(always)]
103-
fn borrow_count(&self) -> &Cell<usize> {
103+
fn raw_lock(&self) -> &RawLock {
104104
match self {
105-
Self::Default(inner) => &inner.borrow_count,
105+
Self::Default(inner) => &inner.raw_lock,
106106
#[cfg(feature = "serialize")]
107-
Self::Serializable(inner) => &inner.borrow_count,
107+
Self::Serializable(inner) => &inner.raw_lock,
108108
}
109109
}
110110

@@ -139,7 +139,6 @@ impl Serialize for UserDataStorage<()> {
139139
/// A type that provides interior mutability for a userdata value (thread-safe).
140140
pub(crate) struct UserDataCell<T> {
141141
raw_lock: RawLock,
142-
borrow_count: Cell<usize>,
143142
value: UnsafeCell<T>,
144143
}
145144

@@ -153,7 +152,6 @@ impl<T> UserDataCell<T> {
153152
fn new(value: T) -> Self {
154153
UserDataCell {
155154
raw_lock: RawLock::INIT,
156-
borrow_count: Cell::new(0),
157155
value: UnsafeCell::new(value),
158156
}
159157
}
@@ -303,7 +301,6 @@ impl<T> Drop for UserDataBorrowRef<'_, T> {
303301
#[inline]
304302
fn drop(&mut self) {
305303
unsafe {
306-
self.0.borrow_count().set(self.0.borrow_count().get() - 1);
307304
self.0.raw_lock().unlock_shared();
308305
}
309306
}
@@ -331,7 +328,6 @@ impl<'a, T> TryFrom<&'a UserDataVariant<T>> for UserDataBorrowRef<'a, T> {
331328
if !variant.raw_lock().try_lock_shared() {
332329
return Err(Error::UserDataBorrowError);
333330
}
334-
variant.borrow_count().set(variant.borrow_count().get() + 1);
335331
Ok(UserDataBorrowRef(variant))
336332
}
337333
}
@@ -342,7 +338,6 @@ impl<T> Drop for UserDataBorrowMut<'_, T> {
342338
#[inline]
343339
fn drop(&mut self) {
344340
unsafe {
345-
self.0.borrow_count().set(self.0.borrow_count().get() - 1);
346341
self.0.raw_lock().unlock_exclusive();
347342
}
348343
}
@@ -372,7 +367,6 @@ impl<'a, T> TryFrom<&'a UserDataVariant<T>> for UserDataBorrowMut<'a, T> {
372367
if !variant.raw_lock().try_lock_exclusive() {
373368
return Err(Error::UserDataBorrowMutError);
374369
}
375-
variant.borrow_count().set(variant.borrow_count().get() + 1);
376370
Ok(UserDataBorrowMut(variant))
377371
}
378372
}
@@ -489,11 +483,15 @@ impl<T> UserDataStorage<T> {
489483
Self::Scoped(ScopedUserDataVariant::Boxed(RefCell::new(data)))
490484
}
491485

486+
/// Returns `true` if it's safe to destroy the container.
487+
///
488+
/// It's safe to destroy the container if the reference count is greater than 1 or the lock is
489+
/// not acquired.
492490
#[inline(always)]
493-
pub(crate) fn is_borrowed(&self) -> bool {
491+
pub(crate) fn is_safe_to_destroy(&self) -> bool {
494492
match self {
495-
Self::Owned(variant) => variant.borrow_count().get() > 0,
496-
Self::Scoped(_) => true,
493+
Self::Owned(variant) => variant.strong_count() > 1 || !variant.raw_lock().is_locked(),
494+
Self::Scoped(_) => false,
497495
}
498496
}
499497

src/userdata/lock.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pub(crate) trait UserDataLock {
22
const INIT: Self;
33

4+
fn is_locked(&self) -> bool;
45
fn try_lock_shared(&self) -> bool;
56
fn try_lock_exclusive(&self) -> bool;
67

@@ -25,6 +26,11 @@ mod lock_impl {
2526
#[allow(clippy::declare_interior_mutable_const)]
2627
const INIT: Self = Cell::new(UNUSED);
2728

29+
#[inline(always)]
30+
fn is_locked(&self) -> bool {
31+
self.get() != UNUSED
32+
}
33+
2834
#[inline(always)]
2935
fn try_lock_shared(&self) -> bool {
3036
let flag = self.get().wrapping_add(1);
@@ -71,6 +77,11 @@ mod lock_impl {
7177
#[allow(clippy::declare_interior_mutable_const)]
7278
const INIT: Self = <Self as parking_lot::lock_api::RawRwLock>::INIT;
7379

80+
#[inline(always)]
81+
fn is_locked(&self) -> bool {
82+
RawRwLock::is_locked(self)
83+
}
84+
7485
#[inline(always)]
7586
fn try_lock_shared(&self) -> bool {
7687
RawRwLock::try_lock_shared(self)

src/userdata/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub(crate) fn is_sync<T>() -> bool {
3636

3737
pub(super) unsafe extern "C-unwind" fn userdata_destructor<T>(state: *mut ffi::lua_State) -> c_int {
3838
let ud = get_userdata::<UserDataStorage<T>>(state, -1);
39-
if !(*ud).is_borrowed() {
39+
if (*ud).is_safe_to_destroy() {
4040
take_userdata::<UserDataStorage<T>>(state);
4141
ffi::lua_pushboolean(state, 1);
4242
} else {

tests/userdata.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ fn test_userdata_destroy() -> Result<()> {
410410
let ud_ref = ud.borrow::<MyUserdata>()?;
411411
// With active `UserDataRef` this methods only marks userdata as destructed
412412
// without running destructor
413-
ud.destroy()?;
413+
ud.destroy().unwrap();
414414
assert_eq!(Arc::strong_count(&rc), 2);
415415
drop(ud_ref);
416416
assert_eq!(Arc::strong_count(&rc), 1);
@@ -419,7 +419,7 @@ fn test_userdata_destroy() -> Result<()> {
419419
let ud = lua.create_userdata(MyUserdata(rc.clone()))?;
420420
lua.globals().set("ud", &ud)?;
421421
lua.load("ud:try_destroy()").exec().unwrap();
422-
ud.destroy()?;
422+
ud.destroy().unwrap();
423423
assert_eq!(Arc::strong_count(&rc), 1);
424424

425425
Ok(())

0 commit comments

Comments
 (0)