| 88 | } |
| 89 | |
| 90 | fn run_with_context<F>( |
| 91 | &self, |
| 92 | jen: &PyObject, |
| 93 | vm: &VirtualMachine, |
| 94 | func: F, |
| 95 | ) -> PyResult<ExecutionResult> |
| 96 | where |
| 97 | F: FnOnce(&Py<Frame>) -> PyResult<ExecutionResult>, |
| 98 | { |
| 99 | if self.running.compare_exchange(false, true).is_err() { |
| 100 | return Err(vm.new_value_error(format!("{} already executing", gen_name(jen, vm)))); |
| 101 | } |
| 102 | |
| 103 | // SAFETY: running.compare_exchange guarantees exclusive access |
| 104 | let gen_exc = unsafe { self.exception.swap(None) }; |
| 105 | let exception_ptr = &self.exception as *const PyAtomicRef<Option<PyBaseException>>; |
| 106 | |
| 107 | let result = vm.resume_gen_frame(&self.frame, gen_exc, |f| { |
| 108 | let result = func(f); |
| 109 | // SAFETY: exclusive access guaranteed by running flag |
| 110 | let _old = unsafe { (*exception_ptr).swap(vm.current_exception()) }; |
| 111 | result |
| 112 | }); |
| 113 | |
| 114 | self.running.store(false); |
| 115 | result |
| 116 | } |
| 117 | |
| 118 | fn finalize_send_result( |
| 119 | &self, |