(vm: &VirtualMachine, f: impl FnOnce() -> R)
| 215 | /// `Py_BEGIN_ALLOW_THREADS` / `Py_END_ALLOW_THREADS` equivalent. |
| 216 | #[cfg(all(unix, feature = "threading"))] |
| 217 | pub fn allow_threads<R>(vm: &VirtualMachine, f: impl FnOnce() -> R) -> R { |
| 218 | // Preserve save/restore semantics: |
| 219 | // only detach if this call observed ATTACHED at entry, and always restore |
| 220 | // on unwind. |
| 221 | let should_transition = CURRENT_THREAD_SLOT.with(|slot| { |
| 222 | slot.borrow() |
| 223 | .as_ref() |
| 224 | .is_some_and(|s| s.state.load(Ordering::Acquire) == THREAD_ATTACHED) |
| 225 | }); |
| 226 | if !should_transition { |
| 227 | return f(); |
| 228 | } |
| 229 | |
| 230 | detach_thread(); |
| 231 | let reattach_guard = scopeguard::guard(vm, attach_thread); |
| 232 | let result = f(); |
| 233 | drop(reattach_guard); |
| 234 | result |
| 235 | } |
| 236 | |
| 237 | /// No-op on non-unix or non-threading builds. |
| 238 | #[cfg(not(all(unix, feature = "threading")))] |
no test coverage detected