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 }