1use crate::value::Slot;
2use crate::vm::StackError;
3use std::cell::Cell;
4use std::fmt;
5use std::ops;
6
7#[derive(Debug, Clone, Default)]
8pub(super) struct Access(Cell<isize>);
9
10impl Access {
11 #[inline]
13 pub(super) fn test_shared(&self, slot: Slot) -> Result<(), StackError> {
14 let b = self.0.get().wrapping_sub(1);
15
16 if b >= 0 {
17 return Err(StackError::SlotInaccessibleShared { slot });
18 }
19
20 Ok(())
21 }
22
23 #[inline]
25 pub(super) fn shared(&self, slot: Slot) -> Result<(), StackError> {
26 let b = self.0.get().wrapping_sub(1);
27
28 if b >= 0 {
29 return Err(StackError::SlotInaccessibleShared { slot });
30 }
31
32 self.0.set(b);
33 Ok(())
34 }
35
36 #[inline]
38 pub(super) fn release_shared(&self) {
39 let b = self.0.get().wrapping_add(1);
40 debug_assert!(b <= 0);
41 self.0.set(b);
42 }
43
44 #[inline]
46 pub(super) fn release_exclusive(&self) {
47 let b = self.0.get().wrapping_sub(1);
48 debug_assert!(b == 0);
49 self.0.set(b);
50 }
51
52 #[inline]
54 pub(super) fn exclusive(&self, slot: Slot) -> Result<(), StackError> {
55 let b = self.0.get().wrapping_add(1);
56
57 if b != 1 {
58 return Err(StackError::SlotInaccessibleExclusive { slot });
59 }
60
61 self.0.set(b);
62 Ok(())
63 }
64}
65
66pub struct RawRefGuard {
68 pub(super) access: *const Access,
69}
70
71impl Drop for RawRefGuard {
72 fn drop(&mut self) {
73 unsafe { (*self.access).release_shared() };
74 }
75}
76
77pub struct Ref<'a, T: ?Sized + 'a> {
87 pub(super) value: &'a T,
88 pub(super) raw: RawRefGuard,
89}
90
91impl<'a, T: ?Sized> Ref<'a, T> {
92 pub unsafe fn unsafe_into_ref<'out>(this: Self) -> (&'out T, RawRefGuard) {
100 let value = &*(this.value as *const _);
101 (value, this.raw)
102 }
103}
104
105impl<T: ?Sized> ops::Deref for Ref<'_, T> {
106 type Target = T;
107
108 fn deref(&self) -> &Self::Target {
109 self.value
110 }
111}
112
113impl<T: ?Sized> fmt::Debug for Ref<'_, T>
114where
115 T: fmt::Debug,
116{
117 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
118 fmt::Debug::fmt(self.value, fmt)
119 }
120}
121
122pub struct RawMutGuard {
124 pub(super) access: *const Access,
125}
126
127impl Drop for RawMutGuard {
128 fn drop(&mut self) {
129 unsafe { (*self.access).release_exclusive() }
130 }
131}
132
133pub struct Mut<'a, T: ?Sized> {
143 pub(super) value: &'a mut T,
144 pub(super) raw: RawMutGuard,
145}
146
147impl<'a, T: ?Sized> Mut<'a, T> {
148 pub unsafe fn unsafe_into_mut<'out>(this: Self) -> (&'out mut T, RawMutGuard) {
156 let value = &mut *(this.value as *mut _);
157 (value, this.raw)
158 }
159}
160
161impl<T: ?Sized> ops::Deref for Mut<'_, T> {
162 type Target = T;
163
164 fn deref(&self) -> &Self::Target {
165 self.value
166 }
167}
168
169impl<T: ?Sized> ops::DerefMut for Mut<'_, T> {
170 fn deref_mut(&mut self) -> &mut Self::Target {
171 self.value
172 }
173}