| 142 | /// If `out` is provided, the result is delivered to that channel asynchronously. |
| 143 | #[pyo3(signature = (spec, *args, out=None, **kwargs))] |
| 144 | fn go( |
| 145 | &self, |
| 146 | py: Python<'_>, |
| 147 | spec: &Bound<'_, PyAny>, |
| 148 | args: &Bound<'_, PyTuple>, |
| 149 | out: Option<PyChannel>, |
| 150 | kwargs: Option<&Bound<'_, PyDict>>, |
| 151 | ) -> PyResult<PyTaskHandle> { |
| 152 | let out_channel = out.map(|c| c.inner); |
| 153 | |
| 154 | if let Ok(map_spec) = spec.extract::<PyMapSpec>() { |
| 155 | reject_callable_args_for_spec(args, kwargs)?; |
| 156 | let handle = TaskHandle::new(); |
| 157 | let h2 = handle.clone(); |
| 158 | |
| 159 | py.allow_threads(|| { |
| 160 | h2.set_running_compute(); |
| 161 | match execute_map(&map_spec) { |
| 162 | Ok(buf) => { |
| 163 | if let Some(ch) = out_channel { |
| 164 | h2.set_delivery_queued(TaskResult::Buffer(buf.clone())); |
| 165 | submit_delivery(DeliveryJob { |
| 166 | task: h2, |
| 167 | channel: ch, |
| 168 | buffer: buf, |
| 169 | }); |
| 170 | } else { |
| 171 | h2.complete(TaskResult::Buffer(buf)); |
| 172 | } |
| 173 | } |
| 174 | Err(e) => h2.fail(e), |
| 175 | } |
| 176 | }); |
| 177 | |
| 178 | Ok(PyTaskHandle::new(handle)) |
| 179 | } else if let Ok(reduce_spec) = spec.extract::<PyReduceSpec>() { |
| 180 | reject_callable_args_for_spec(args, kwargs)?; |
| 181 | let handle = TaskHandle::new(); |
| 182 | let h2 = handle.clone(); |
| 183 | |
| 184 | py.allow_threads(|| { |
| 185 | h2.set_running_compute(); |
| 186 | match execute_reduce(&reduce_spec) { |
| 187 | Ok(v) => { |
| 188 | if let Some(ch) = out_channel { |
| 189 | h2.set_delivery_queued(TaskResult::Scalar(v)); |
| 190 | submit_delivery(DeliveryJob { |
| 191 | task: h2, |
| 192 | channel: ch, |
| 193 | buffer: Buffer::from_f64_vec(vec![v]), |
| 194 | }); |
| 195 | } else { |
| 196 | h2.complete(TaskResult::Scalar(v)); |
| 197 | } |
| 198 | } |
| 199 | Err(e) => h2.fail(e), |
| 200 | } |
| 201 | }); |