Mercurial > public > mercurial-scm > hg
comparison rust/pyo3-sharedref/tests/test_sharedref.rs @ 52609:d1e304025b90
rust-pyo3-sharedref: replaced borrow/borrow_mut with RwLock namings
The "borrow" word had way too many uses in this context. Originally,
it came from the rust-cpython version, which is based on `RefCell`.
Before this change, we had untracktable stacks of borrows (first the
`Bound`, then the `PySharedRefCell`).
In any case, the change to `RwLock` is far from being neutral, and
we may need in a future without GIL to also expose blocking methods, to
account for in-Rust possible concurrency. Using `read()` and `write()`
right now matches our PyO3 habits anyway, where all non-Sync objects
have to be wrapped in a RwLock.
author | Georges Racinet <georges.racinet@cloudcrane.io> |
---|---|
date | Sun, 15 Dec 2024 13:58:31 +0100 |
parents | d85514a88706 |
children | c25d345f5aa5 |
comparison
equal
deleted
inserted
replaced
52608:d85514a88706 | 52609:d1e304025b90 |
---|---|
51 owner: &'py Bound<'py, Owner>, | 51 owner: &'py Bound<'py, Owner>, |
52 f: impl FnOnce(&mut String), | 52 f: impl FnOnce(&mut String), |
53 ) -> () { | 53 ) -> () { |
54 let cell = &owner.borrow_mut().string; | 54 let cell = &owner.borrow_mut().string; |
55 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; | 55 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
56 f(&mut shared_ref.borrow_mut()); | 56 f(&mut shared_ref.write()); |
57 } | 57 } |
58 | 58 |
59 #[test] | 59 #[test] |
60 fn test_leaked_borrow() -> PyResult<()> { | 60 fn test_leaked_borrow() -> PyResult<()> { |
61 with_setup(|py, owner| { | 61 with_setup(|py, owner| { |
117 | 117 |
118 /// run `try_borrow_mut` on the `string` field and assert it is not an error | 118 /// run `try_borrow_mut` on the `string` field and assert it is not an error |
119 /// | 119 /// |
120 /// Simply returning the `Result` is not possible, because that is | 120 /// Simply returning the `Result` is not possible, because that is |
121 /// returning a reference to data owned by the function | 121 /// returning a reference to data owned by the function |
122 fn assert_try_borrow_string_mut_ok(owner: &Bound<'_, Owner>) { | 122 fn assert_try_write_string_ok(owner: &Bound<'_, Owner>) { |
123 let cell = &owner.borrow().string; | 123 let cell = &owner.borrow().string; |
124 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; | 124 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
125 assert!(shared_ref.try_borrow_mut().is_ok()); | 125 assert!(shared_ref.try_write().is_ok()); |
126 } | 126 } |
127 | 127 |
128 fn assert_try_borrow_string_mut_err(owner: &Bound<'_, Owner>) { | 128 fn assert_try_write_string_err(owner: &Bound<'_, Owner>) { |
129 let cell = &owner.borrow().string; | 129 let cell = &owner.borrow().string; |
130 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; | 130 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
131 assert!(shared_ref.try_borrow_mut().is_err()); | 131 assert!(shared_ref.try_write().is_err()); |
132 } | 132 } |
133 | 133 |
134 fn assert_try_borrow_string_err(owner: &Bound<'_, Owner>) { | 134 fn assert_try_read_string_err(owner: &Bound<'_, Owner>) { |
135 let cell = &owner.borrow().string; | 135 let cell = &owner.borrow().string; |
136 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; | 136 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
137 assert!(shared_ref.try_borrow().is_err()); | 137 assert!(shared_ref.try_read().is_err()); |
138 } | 138 } |
139 | 139 |
140 #[test] | 140 #[test] |
141 fn test_try_borrow_mut_while_leaked_ref() -> PyResult<()> { | 141 fn test_try_write_while_leaked_ref() -> PyResult<()> { |
142 with_setup(|py, owner| { | 142 with_setup(|py, owner| { |
143 assert_try_borrow_string_mut_ok(owner); | 143 assert_try_write_string_ok(owner); |
144 let leaked = leak_string(owner); | 144 let leaked = leak_string(owner); |
145 { | 145 { |
146 let _leaked_ref = unsafe { leaked.try_borrow(py) }.unwrap(); | 146 let _leaked_ref = unsafe { leaked.try_borrow(py) }.unwrap(); |
147 assert_try_borrow_string_mut_err(owner); | 147 assert_try_write_string_err(owner); |
148 { | 148 { |
149 let _leaked_ref2 = unsafe { leaked.try_borrow(py) }.unwrap(); | 149 let _leaked_ref2 = unsafe { leaked.try_borrow(py) }.unwrap(); |
150 assert_try_borrow_string_mut_err(owner); | 150 assert_try_write_string_err(owner); |
151 } | 151 } |
152 assert_try_borrow_string_mut_err(owner); | 152 assert_try_write_string_err(owner); |
153 } | 153 } |
154 assert_try_borrow_string_mut_ok(owner); | 154 assert_try_write_string_ok(owner); |
155 Ok(()) | 155 Ok(()) |
156 }) | 156 }) |
157 } | 157 } |
158 | 158 |
159 #[test] | 159 #[test] |
160 fn test_try_borrow_mut_while_leaked_ref_mut() -> PyResult<()> { | 160 fn test_try_write_while_leaked_ref_mut() -> PyResult<()> { |
161 with_setup(|py, owner| { | 161 with_setup(|py, owner| { |
162 assert_try_borrow_string_mut_ok(owner); | 162 assert_try_write_string_ok(owner); |
163 let leaked = leak_string(owner); | 163 let leaked = leak_string(owner); |
164 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; | 164 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
165 { | 165 { |
166 let _leaked_ref = | 166 let _leaked_ref = |
167 unsafe { leaked_iter.try_borrow_mut(py) }.unwrap(); | 167 unsafe { leaked_iter.try_borrow_mut(py) }.unwrap(); |
168 assert_try_borrow_string_mut_err(owner); | 168 assert_try_write_string_err(owner); |
169 } | 169 } |
170 assert_try_borrow_string_mut_ok(owner); | 170 assert_try_write_string_ok(owner); |
171 Ok(()) | 171 Ok(()) |
172 }) | 172 }) |
173 } | 173 } |
174 | 174 |
175 #[test] | 175 #[test] |
176 fn test_try_leak_while_borrow_mut() -> PyResult<()> { | 176 fn test_try_leak_while_write() -> PyResult<()> { |
177 with_setup(|_py, owner| { | 177 with_setup(|_py, owner| { |
178 let cell = &owner.borrow().string; | 178 let cell = &owner.borrow().string; |
179 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; | 179 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
180 let _mut_ref = shared_ref.borrow_mut(); | 180 let _mut_ref = shared_ref.write(); |
181 | 181 |
182 assert!(try_leak_string(owner).is_err()); | 182 assert!(try_leak_string(owner).is_err()); |
183 Ok(()) | 183 Ok(()) |
184 }) | 184 }) |
185 } | 185 } |
186 | 186 |
187 #[test] | 187 #[test] |
188 #[should_panic(expected = "already mutably borrowed")] | 188 #[should_panic(expected = "already mutably borrowed")] |
189 fn test_leak_while_borrow_mut() { | 189 fn test_leak_while_write() { |
190 with_setup(|_py, owner| { | 190 with_setup(|_py, owner| { |
191 let cell = &owner.borrow().string; | 191 let cell = &owner.borrow().string; |
192 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; | 192 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
193 let _mut_ref = shared_ref.borrow_mut(); | 193 let _mut_ref = shared_ref.write(); |
194 | 194 |
195 leak_string(owner); | 195 leak_string(owner); |
196 Ok(()) | 196 Ok(()) |
197 }) | 197 }) |
198 .expect("should already have panicked") | 198 .expect("should already have panicked") |
199 } | 199 } |
200 | 200 |
201 #[test] | 201 #[test] |
202 fn test_try_borrow_mut_while_borrow() -> PyResult<()> { | 202 fn test_try_write_while_borrow() -> PyResult<()> { |
203 with_setup(|_py, owner| { | 203 with_setup(|_py, owner| { |
204 let cell = &owner.borrow().string; | 204 let cell = &owner.borrow().string; |
205 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; | 205 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
206 let _ref = shared_ref.borrow(); | 206 let _ref = shared_ref.read(); |
207 | 207 |
208 assert_try_borrow_string_mut_err(owner); | 208 assert_try_write_string_err(owner); |
209 Ok(()) | 209 Ok(()) |
210 }) | 210 }) |
211 } | 211 } |
212 | 212 |
213 #[test] | 213 #[test] |
214 #[should_panic(expected = "already borrowed")] | 214 #[should_panic(expected = "already borrowed")] |
215 fn test_borrow_mut_while_borrow() { | 215 fn test_write_while_borrow() { |
216 with_setup(|_py, owner| { | 216 with_setup(|_py, owner| { |
217 let cell = &owner.borrow().string; | 217 let cell = &owner.borrow().string; |
218 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; | 218 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
219 let _ref = shared_ref.borrow(); | 219 let _ref = shared_ref.read(); |
220 | 220 |
221 let shared_ref2 = unsafe { cell.borrow_with_owner(owner) }; | 221 let shared_ref2 = unsafe { cell.borrow_with_owner(owner) }; |
222 let _mut_ref = shared_ref2.borrow_mut(); | 222 let _mut_ref = shared_ref2.write(); |
223 Ok(()) | 223 Ok(()) |
224 }) | 224 }) |
225 .expect("should already have panicked") | 225 .expect("should already have panicked") |
226 } | 226 } |
227 | 227 |
228 #[test] | 228 #[test] |
229 fn test_try_borrow_while_borrow_mut() -> PyResult<()> { | 229 fn test_try_borrow_while_write() -> PyResult<()> { |
230 with_setup(|_py, owner| { | 230 with_setup(|_py, owner| { |
231 let cell = &owner.borrow().string; | 231 let cell = &owner.borrow().string; |
232 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; | 232 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
233 let _mut_ref = shared_ref.borrow_mut(); | 233 let _mut_ref = shared_ref.write(); |
234 | 234 |
235 assert_try_borrow_string_err(owner); | 235 assert_try_read_string_err(owner); |
236 Ok(()) | 236 Ok(()) |
237 }) | 237 }) |
238 } | 238 } |
239 | 239 |
240 #[test] | 240 #[test] |
241 #[should_panic(expected = "already mutably borrowed")] | 241 #[should_panic(expected = "already mutably borrowed")] |
242 fn test_borrow_while_borrow_mut() { | 242 fn test_borrow_while_write() { |
243 with_setup(|_py, owner| { | 243 with_setup(|_py, owner| { |
244 let cell = &owner.borrow().string; | 244 let cell = &owner.borrow().string; |
245 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; | 245 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
246 let _mut_ref = shared_ref.borrow_mut(); | 246 let _mut_ref = shared_ref.write(); |
247 | 247 |
248 let shared_ref2 = unsafe { cell.borrow_with_owner(owner) }; | 248 let shared_ref2 = unsafe { cell.borrow_with_owner(owner) }; |
249 let _ref = shared_ref2.borrow(); | 249 let _ref = shared_ref2.read(); |
250 Ok(()) | 250 Ok(()) |
251 }) | 251 }) |
252 .expect("should already have panicked") | 252 .expect("should already have panicked") |
253 } | 253 } |