MCPcopy Create free account
hub / github.com/apache/arrow / WorkerLoop

Function WorkerLoop

cpp/src/arrow/util/thread_pool.cc:448–520  ·  view source on GitHub ↗

The worker loop is an independent function so that it can keep running after the ThreadPool is destroyed.

Source from the content-addressed store, hash-verified

446// The worker loop is an independent function so that it can keep running
447// after the ThreadPool is destroyed.
448static void WorkerLoop(std::shared_ptr<ThreadPool::State> state,
449 std::list<std::thread>::iterator it) {
450 std::unique_lock<std::mutex> lock(state->mutex_);
451
452 // Since we hold the lock, `it` now points to the correct thread object
453 // (LaunchWorkersUnlocked has exited)
454 DCHECK_EQ(std::this_thread::get_id(), it->get_id());
455
456 // If too many threads, we should secede from the pool
457 const auto should_secede = [&]() -> bool {
458 return state->workers_.size() > static_cast<size_t>(state->desired_capacity_);
459 };
460
461 while (true) {
462 // By the time this thread is started, some tasks may have been pushed
463 // or shutdown could even have been requested. So we only wait on the
464 // condition variable at the end of the loop.
465
466 // Execute pending tasks if any
467 while (!state->pending_tasks_.empty() && !state->quick_shutdown_) {
468 // We check this opportunistically at each loop iteration since
469 // it releases the lock below.
470 if (should_secede()) {
471 break;
472 }
473
474 DCHECK_GE(state->tasks_queued_or_running_, 0);
475 {
476 Task task = std::move(const_cast<Task&>(state->pending_tasks_.top().task));
477 state->pending_tasks_.pop();
478 StopToken* stop_token = &task.stop_token;
479 lock.unlock();
480 if (!stop_token->IsStopRequested()) {
481 std::move(task.callable)();
482 } else {
483 if (task.stop_callback) {
484 std::move(task.stop_callback)(stop_token->Poll());
485 }
486 }
487 {
488 auto tmp_task = std::move(task); // release resources before waiting for lock
489 ARROW_UNUSED(tmp_task);
490 }
491 lock.lock();
492 }
493 if (ARROW_PREDICT_FALSE(--state->tasks_queued_or_running_ == 0)) {
494 state->cv_idle_.notify_all();
495 }
496 }
497 // Now either the queue is empty *or* a quick shutdown was requested
498 if (state->please_shutdown_ || should_secede()) {
499 break;
500 }
501 // Wait for next wakeup
502 state->cv_.wait(lock);
503 }
504 DCHECK_GE(state->tasks_queued_or_running_, 0);
505

Callers 1

LaunchWorkersUnlockedMethod · 0.85

Calls 5

IsStopRequestedMethod · 0.80
PollMethod · 0.80
push_backMethod · 0.80
sizeMethod · 0.45
emptyMethod · 0.45

Tested by

no test coverage detected