equal
deleted
inserted
replaced
55 borrow_count: AtomicUsize, |
55 borrow_count: AtomicUsize, |
56 generation: AtomicUsize, |
56 generation: AtomicUsize, |
57 } |
57 } |
58 |
58 |
59 impl PySharedState { |
59 impl PySharedState { |
60 fn try_borrow_mut<'a, T>( |
|
61 &'a self, |
|
62 py: Python<'a>, |
|
63 pyrefmut: RefMut<'a, T>, |
|
64 ) -> PyResult<RefMut<'a, T>> { |
|
65 match self.current_borrow_count(py) { |
|
66 0 => { |
|
67 // Note that this wraps around to the same value if mutably |
|
68 // borrowed more than usize::MAX times, which wouldn't happen |
|
69 // in practice. |
|
70 self.generation.fetch_add(1, Ordering::Relaxed); |
|
71 Ok(pyrefmut) |
|
72 } |
|
73 _ => Err(AlreadyBorrowed::new( |
|
74 py, |
|
75 "Cannot borrow mutably while immutably borrowed", |
|
76 )), |
|
77 } |
|
78 } |
|
79 |
|
80 /// Return a reference to the wrapped data and its state with an |
60 /// Return a reference to the wrapped data and its state with an |
81 /// artificial static lifetime. |
61 /// artificial static lifetime. |
82 /// We need to be protected by the GIL for thread-safety. |
62 /// We need to be protected by the GIL for thread-safety. |
83 /// |
63 /// |
84 /// # Safety |
64 /// # Safety |
111 } |
91 } |
112 |
92 |
113 fn current_generation(&self, _py: Python) -> usize { |
93 fn current_generation(&self, _py: Python) -> usize { |
114 self.generation.load(Ordering::Relaxed) |
94 self.generation.load(Ordering::Relaxed) |
115 } |
95 } |
|
96 |
|
97 fn increment_generation(&self, py: Python) { |
|
98 assert_eq!(self.current_borrow_count(py), 0); |
|
99 // Note that this wraps around to the same value if mutably |
|
100 // borrowed more than usize::MAX times, which wouldn't happen |
|
101 // in practice. |
|
102 self.generation.fetch_add(1, Ordering::Relaxed); |
|
103 } |
116 } |
104 } |
117 |
105 |
118 /// Helper to keep the borrow count updated while the shared object is |
106 /// Helper to keep the borrow count updated while the shared object is |
119 /// immutably borrowed without using the `RefCell` interface. |
107 /// immutably borrowed without using the `RefCell` interface. |
120 struct BorrowPyShared<'a> { |
108 struct BorrowPyShared<'a> { |
168 |
156 |
169 fn try_borrow_mut<'a>( |
157 fn try_borrow_mut<'a>( |
170 &'a self, |
158 &'a self, |
171 py: Python<'a>, |
159 py: Python<'a>, |
172 ) -> PyResult<RefMut<'a, T>> { |
160 ) -> PyResult<RefMut<'a, T>> { |
|
161 if self.py_shared_state.current_borrow_count(py) > 0 { |
|
162 return Err(AlreadyBorrowed::new( |
|
163 py, |
|
164 "Cannot borrow mutably while immutably borrowed", |
|
165 )); |
|
166 } |
173 let inner_ref = self |
167 let inner_ref = self |
174 .inner |
168 .inner |
175 .try_borrow_mut() |
169 .try_borrow_mut() |
176 .map_err(|e| AlreadyBorrowed::new(py, e.to_string()))?; |
170 .map_err(|e| AlreadyBorrowed::new(py, e.to_string()))?; |
177 self.py_shared_state.try_borrow_mut(py, inner_ref) |
171 self.py_shared_state.increment_generation(py); |
|
172 Ok(inner_ref) |
178 } |
173 } |
179 } |
174 } |
180 |
175 |
181 /// Sharable data member of type `T` borrowed from the `PyObject`. |
176 /// Sharable data member of type `T` borrowed from the `PyObject`. |
182 pub struct PySharedRef<'a, T> { |
177 pub struct PySharedRef<'a, T> { |