| 207 | // `fun`). |
| 208 | template <typename T> |
| 209 | arrow::Future<T> SafeCallIntoRAsync(std::function<arrow::Result<T>(void)> fun, |
| 210 | std::string reason = "unspecified") { |
| 211 | MainRThread& main_r_thread = MainRThread::GetInstance(); |
| 212 | if (main_r_thread.IsMainThread()) { |
| 213 | // If we're on the main thread, run the task immediately and let |
| 214 | // the cpp11::unwind_exception be thrown since it will be caught |
| 215 | // at the top level. |
| 216 | return fun(); |
| 217 | } else if (main_r_thread.CanExecuteSafeCallIntoR()) { |
| 218 | // If we are not on the main thread and have an Executor, |
| 219 | // use it to run the task on the main R thread. We can't throw |
| 220 | // a cpp11::unwind_exception here, so we need to propagate it back |
| 221 | // to RunWithCapturedR through the MainRThread instance. |
| 222 | return DeferNotOk(main_r_thread.Executor()->Submit([fun, |
| 223 | reason]() -> arrow::Result<T> { |
| 224 | // This occurs when some other R code that was previously scheduled to run |
| 225 | // has errored, in which case we skip execution and let the original |
| 226 | // error surface. |
| 227 | if (MainRThread::GetInstance().HasError()) { |
| 228 | return arrow::Status::Cancelled("Previous R code execution error (", reason, ")"); |
| 229 | } |
| 230 | |
| 231 | try { |
| 232 | WithoutSignalHandlerContext context; |
| 233 | return fun(); |
| 234 | } catch (cpp11::unwind_exception& e) { |
| 235 | // Set the MainRThread error so that subsequent calls to SafeCallIntoR |
| 236 | // know not to execute R code. |
| 237 | MainRThread::GetInstance().SetError(arrow::StatusUnwindProtect(e.token, reason)); |
| 238 | |
| 239 | // Return an error Status (which is unlikely to surface since RunWithCapturedR |
| 240 | // will preferentially return the MainRThread error). |
| 241 | return arrow::Status::Invalid("R code execution error (", reason, ")"); |
| 242 | } |
| 243 | })); |
| 244 | } else { |
| 245 | return arrow::Status::NotImplemented( |
| 246 | "Call to R (", reason, ") from a non-R thread from an unsupported context"); |
| 247 | } |
| 248 | } |
| 249 | |
| 250 | template <typename T> |
| 251 | arrow::Result<T> SafeCallIntoR(std::function<T(void)> fun, |
nothing calls this directly
no test coverage detected