| 323 | } |
| 324 | |
| 325 | Status TaskSchedulerImpl::ScheduleMore(size_t thread_id, int num_tasks_finished) { |
| 326 | if (aborted_.value.load()) { |
| 327 | return Status::Cancelled("Scheduler cancelled"); |
| 328 | } |
| 329 | |
| 330 | ARROW_DCHECK(register_finished_); |
| 331 | |
| 332 | if (use_sync_execution_) { |
| 333 | return ExecuteMore(thread_id, 1, true); |
| 334 | } |
| 335 | |
| 336 | int num_new_tasks = num_tasks_finished; |
| 337 | for (;;) { |
| 338 | int expected = num_tasks_to_schedule_.value.load(); |
| 339 | if (num_tasks_to_schedule_.value.compare_exchange_strong(expected, 0)) { |
| 340 | num_new_tasks += expected; |
| 341 | break; |
| 342 | } |
| 343 | } |
| 344 | if (num_new_tasks == 0) { |
| 345 | return Status::OK(); |
| 346 | } |
| 347 | |
| 348 | const auto& tasks = PickTasks(num_new_tasks); |
| 349 | if (static_cast<int>(tasks.size()) < num_new_tasks) { |
| 350 | num_tasks_to_schedule_.value += num_new_tasks - static_cast<int>(tasks.size()); |
| 351 | } |
| 352 | |
| 353 | bool expected_might_have_missed_tasks = true; |
| 354 | if (tasks_added_recently_.value.compare_exchange_strong( |
| 355 | expected_might_have_missed_tasks, false)) { |
| 356 | if (tasks.empty()) { |
| 357 | // num_tasks_finished has already been added to num_tasks_to_schedule so |
| 358 | // pass 0 here. |
| 359 | return ScheduleMore(thread_id); |
| 360 | } |
| 361 | } |
| 362 | |
| 363 | for (size_t i = 0; i < tasks.size(); ++i) { |
| 364 | int group_id = tasks[i].first; |
| 365 | int64_t task_id = tasks[i].second; |
| 366 | RETURN_NOT_OK(schedule_impl_([this, group_id, task_id](size_t thread_id) -> Status { |
| 367 | bool task_group_finished = false; |
| 368 | // PostExecuteTask must be called later if any error ocurres during task execution |
| 369 | // (including ScheduleMore), so we preserve the status. |
| 370 | auto status = [&]() { |
| 371 | RETURN_NOT_OK(ScheduleMore(thread_id, 1)); |
| 372 | return ExecuteTask(thread_id, group_id, task_id, &task_group_finished); |
| 373 | }(); |
| 374 | |
| 375 | if (!status.ok()) { |
| 376 | task_group_finished = PostExecuteTask(thread_id, group_id); |
| 377 | } |
| 378 | |
| 379 | if (task_group_finished) { |
| 380 | bool all_task_groups_finished = false; |
| 381 | RETURN_NOT_OK( |
| 382 | OnTaskGroupFinished(thread_id, group_id, &all_task_groups_finished)); |