mlua_codemp_patch/userdata/
lock.rs

1pub(crate) trait UserDataLock {
2    const INIT: Self;
3
4    fn try_lock_shared(&self) -> bool;
5    fn try_lock_exclusive(&self) -> bool;
6
7    unsafe fn unlock_shared(&self);
8    unsafe fn unlock_exclusive(&self);
9}
10
11pub(crate) use lock_impl::RawLock;
12
13#[cfg(not(feature = "send"))]
14mod lock_impl {
15    use std::cell::Cell;
16
17    // Positive values represent the number of read references.
18    // Negative values represent the number of write references (only one allowed).
19    pub(crate) type RawLock = Cell<isize>;
20
21    const UNUSED: isize = 0;
22
23    impl super::UserDataLock for RawLock {
24        #[allow(clippy::declare_interior_mutable_const)]
25        const INIT: Self = Cell::new(UNUSED);
26
27        #[inline(always)]
28        fn try_lock_shared(&self) -> bool {
29            let flag = self.get().wrapping_add(1);
30            if flag <= UNUSED {
31                return false;
32            }
33            self.set(flag);
34            true
35        }
36
37        #[inline(always)]
38        fn try_lock_exclusive(&self) -> bool {
39            let flag = self.get();
40            if flag != UNUSED {
41                return false;
42            }
43            self.set(UNUSED - 1);
44            true
45        }
46
47        #[inline(always)]
48        unsafe fn unlock_shared(&self) {
49            let flag = self.get();
50            debug_assert!(flag > UNUSED);
51            self.set(flag - 1);
52        }
53
54        #[inline(always)]
55        unsafe fn unlock_exclusive(&self) {
56            let flag = self.get();
57            debug_assert!(flag < UNUSED);
58            self.set(flag + 1);
59        }
60    }
61}
62
63#[cfg(feature = "send")]
64mod lock_impl {
65    use parking_lot::lock_api::RawMutex;
66
67    pub(crate) type RawLock = parking_lot::RawMutex;
68
69    impl super::UserDataLock for RawLock {
70        #[allow(clippy::declare_interior_mutable_const)]
71        const INIT: Self = <Self as parking_lot::lock_api::RawMutex>::INIT;
72
73        #[inline(always)]
74        fn try_lock_shared(&self) -> bool {
75            RawLock::try_lock(self)
76        }
77
78        #[inline(always)]
79        fn try_lock_exclusive(&self) -> bool {
80            RawLock::try_lock(self)
81        }
82
83        #[inline(always)]
84        unsafe fn unlock_shared(&self) {
85            RawLock::unlock(self)
86        }
87
88        #[inline(always)]
89        unsafe fn unlock_exclusive(&self) {
90            RawLock::unlock(self)
91        }
92    }
93}