chromium/base/task/thread_pool/thread_group.cc

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/task/thread_pool/thread_group.h"

#include <string_view>
#include <utility>

#include "base/check.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/task/task_features.h"
#include "base/task/thread_pool/task_tracker.h"
#include "build/build_config.h"
#include "third_party/abseil-cpp/absl/base/attributes.h"

#if BUILDFLAG(IS_WIN)
#include "base/win/com_init_check_hook.h"
#include "base/win/scoped_winrt_initializer.h"
#endif

namespace base {
namespace internal {

namespace {

constexpr size_t kMaxNumberOfWorkers =;

// In a background thread group:
// - Blocking calls take more time than in a foreground thread group.
// - We want to minimize impact on foreground work, not maximize execution
//   throughput.
// For these reasons, the timeout to increase the maximum number of concurrent
// tasks when there is a MAY_BLOCK ScopedBlockingCall is *long*. It is not
// infinite because execution throughput should not be reduced forever if a task
// blocks forever.
//
// TODO(fdoray): On platforms without background thread groups, blocking in a
// BEST_EFFORT task should:
// 1. Increment the maximum number of concurrent tasks after a *short* timeout,
//    to allow scheduling of USER_VISIBLE/USER_BLOCKING tasks.
// 2. Increment the maximum number of concurrent BEST_EFFORT tasks after a
//    *long* timeout, because we only want to allow more BEST_EFFORT tasks to be
//    be scheduled concurrently when we believe that a BEST_EFFORT task is
//    blocked forever.
// Currently, only 1. is true as the configuration is per thread group.
// TODO(crbug.com/40612168): Fix racy condition when MayBlockThreshold ==
// BlockedWorkersPoll.
constexpr TimeDelta kForegroundMayBlockThreshold =;
constexpr TimeDelta kForegroundBlockedWorkersPoll =;
constexpr TimeDelta kBackgroundMayBlockThreshold =;
constexpr TimeDelta kBackgroundBlockedWorkersPoll =;

// ThreadGroup that owns the current thread, if any.
ABSL_CONST_INIT thread_local const ThreadGroup* current_thread_group =;

}  // namespace

constexpr ThreadGroup::YieldSortKey ThreadGroup::kMaxYieldSortKey;

void ThreadGroup::BaseScopedCommandsExecutor::ScheduleReleaseTaskSource(
    RegisteredTaskSource task_source) {}

void ThreadGroup::BaseScopedCommandsExecutor::ScheduleAdjustMaxTasks() {}

void ThreadGroup::BaseScopedCommandsExecutor::ScheduleStart(
    scoped_refptr<WorkerThread> worker) {}

ThreadGroup::BaseScopedCommandsExecutor::BaseScopedCommandsExecutor(
    ThreadGroup* outer)
    :{}

ThreadGroup::BaseScopedCommandsExecutor::~BaseScopedCommandsExecutor() {}

void ThreadGroup::BaseScopedCommandsExecutor::FlushWorkerCreation(
    CheckedLock* held_lock) {}

void ThreadGroup::BaseScopedCommandsExecutor::Flush() {}

ThreadGroup::ScopedReenqueueExecutor::ScopedReenqueueExecutor() = default;

ThreadGroup::ScopedReenqueueExecutor::~ScopedReenqueueExecutor() {}

void ThreadGroup::ScopedReenqueueExecutor::
    SchedulePushTaskSourceAndWakeUpWorkers(
        RegisteredTaskSourceAndTransaction transaction_with_task_source,
        ThreadGroup* destination_thread_group) {}

ThreadGroup::ThreadGroup(std::string_view histogram_label,
                         std::string_view thread_group_label,
                         ThreadType thread_type_hint,
                         TrackedRef<TaskTracker> task_tracker,
                         TrackedRef<Delegate> delegate)
    :{}

void ThreadGroup::StartImpl(
    size_t max_tasks,
    size_t max_best_effort_tasks,
    TimeDelta suggested_reclaim_time,
    scoped_refptr<SingleThreadTaskRunner> service_thread_task_runner,
    WorkerThreadObserver* worker_thread_observer,
    WorkerEnvironment worker_environment,
    bool synchronous_thread_start_for_testing,
    std::optional<TimeDelta> may_block_threshold) {}

ThreadGroup::~ThreadGroup() = default;

void ThreadGroup::BindToCurrentThread() {}

void ThreadGroup::UnbindFromCurrentThread() {}

bool ThreadGroup::IsBoundToCurrentThread() const {}

void ThreadGroup::SetMaxTasks(size_t max_tasks) {}

void ThreadGroup::ResetMaxTasks() {}

size_t
ThreadGroup::GetNumAdditionalWorkersForBestEffortTaskSourcesLockRequired()
    const {}

size_t
ThreadGroup::GetNumAdditionalWorkersForForegroundTaskSourcesLockRequired()
    const {}

RegisteredTaskSource ThreadGroup::RemoveTaskSource(
    const TaskSource& task_source) {}

void ThreadGroup::ReEnqueueTaskSourceLockRequired(
    BaseScopedCommandsExecutor* workers_executor,
    ScopedReenqueueExecutor* reenqueue_executor,
    RegisteredTaskSourceAndTransaction transaction_with_task_source) {}

RegisteredTaskSource ThreadGroup::TakeRegisteredTaskSource(
    BaseScopedCommandsExecutor* executor) {}

void ThreadGroup::UpdateSortKeyImpl(BaseScopedCommandsExecutor* executor,
                                    TaskSource::Transaction transaction) {}

void ThreadGroup::PushTaskSourceAndWakeUpWorkersImpl(
    BaseScopedCommandsExecutor* executor,
    RegisteredTaskSourceAndTransaction transaction_with_task_source) {}

void ThreadGroup::EnqueueAllTaskSources(PriorityQueue* new_priority_queue) {}

void ThreadGroup::HandoffAllTaskSourcesToOtherThreadGroup(
    ThreadGroup* destination_thread_group) {}

void ThreadGroup::HandoffNonUserBlockingTaskSourcesToOtherThreadGroup(
    ThreadGroup* destination_thread_group) {}

bool ThreadGroup::ShouldYield(TaskSourceSortKey sort_key) {}

#if BUILDFLAG(IS_WIN)
// static
std::unique_ptr<win::ScopedWindowsThreadEnvironment>
ThreadGroup::GetScopedWindowsThreadEnvironment(WorkerEnvironment environment) {
  std::unique_ptr<win::ScopedWindowsThreadEnvironment> scoped_environment;
  if (environment == WorkerEnvironment::COM_MTA) {
    scoped_environment = std::make_unique<win::ScopedWinrtInitializer>();
  }
  // Continuing execution with an uninitialized apartment may lead to broken
  // program invariants later on.
  CHECK(!scoped_environment || scoped_environment->Succeeded());
  return scoped_environment;
}
#endif

// static
bool ThreadGroup::CurrentThreadHasGroup() {}

size_t ThreadGroup::GetMaxTasksForTesting() const {}

size_t ThreadGroup::GetMaxBestEffortTasksForTesting() const {}

void ThreadGroup::WaitForWorkersIdleLockRequiredForTesting(size_t n) {}

void ThreadGroup::WaitForWorkersIdleForTesting(size_t n) {}

void ThreadGroup::WaitForAllWorkersIdleForTesting() {}

void ThreadGroup::WaitForWorkersCleanedUpForTesting(size_t n) {}

size_t ThreadGroup::GetMaxConcurrentNonBlockedTasksDeprecated() const {}

size_t ThreadGroup::NumberOfWorkersForTesting() const {}

size_t ThreadGroup::NumberOfIdleWorkersForTesting() const {}

size_t ThreadGroup::GetDesiredNumAwakeWorkersLockRequired() const {}

void ThreadGroup::MaybeScheduleAdjustMaxTasksLockRequired(
    BaseScopedCommandsExecutor* executor) {}

bool ThreadGroup::ShouldPeriodicallyAdjustMaxTasksLockRequired() {}

void ThreadGroup::UpdateMinAllowedPriorityLockRequired() {}

void ThreadGroup::DecrementTasksRunningLockRequired(TaskPriority priority) {}

void ThreadGroup::IncrementTasksRunningLockRequired(TaskPriority priority) {}

void ThreadGroup::DecrementMaxTasksLockRequired() {}

void ThreadGroup::IncrementMaxTasksLockRequired() {}

void ThreadGroup::DecrementMaxBestEffortTasksLockRequired() {}

void ThreadGroup::IncrementMaxBestEffortTasksLockRequired() {}

ThreadGroup::InitializedInStart::InitializedInStart() = default;
ThreadGroup::InitializedInStart::~InitializedInStart() = default;

}  // namespace internal
}  // namespace base