(obj: &PyObject, f: F)
| 498 | } |
| 499 | |
| 500 | pub fn with_vm<F, R>(obj: &PyObject, f: F) -> Option<R> |
| 501 | where |
| 502 | F: Fn(&VirtualMachine) -> R, |
| 503 | { |
| 504 | let vm_owns_obj = |interp: NonNull<VirtualMachine>| { |
| 505 | // SAFETY: all references in VM_STACK should be valid |
| 506 | let vm = unsafe { interp.as_ref() }; |
| 507 | obj.fast_isinstance(vm.ctx.types.object_type) |
| 508 | }; |
| 509 | VM_STACK.with(|vms| { |
| 510 | let interp = match vms.borrow().iter().copied().exactly_one() { |
| 511 | Ok(x) => { |
| 512 | debug_assert!(vm_owns_obj(x)); |
| 513 | x |
| 514 | } |
| 515 | Err(mut others) => others.find(|x| vm_owns_obj(*x))?, |
| 516 | }; |
| 517 | // SAFETY: all references in VM_STACK should be valid, and should not be changed or moved |
| 518 | // at least until this function returns and the stack unwinds to an enter_vm() call |
| 519 | let vm = unsafe { interp.as_ref() }; |
| 520 | Some(VM_CURRENT.set(vm, || f(vm))) |
| 521 | }) |
| 522 | } |
| 523 | |
| 524 | #[must_use = "ThreadedVirtualMachine does nothing unless you move it to another thread and call .run()"] |
| 525 | #[cfg(feature = "threading")] |
no test coverage detected