1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/task/thread_pool/thread_pool_instance.h"
6
7 #include <algorithm>
8
9 #include "base/check.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/system/sys_info.h"
12 #include "base/task/thread_pool/thread_pool_impl.h"
13 #include "base/threading/platform_thread.h"
14 #include "base/time/time.h"
15 #include "build/build_config.h"
16
17 namespace base {
18
19 namespace {
20
21 // |g_thread_pool| is intentionally leaked on shutdown.
22 ThreadPoolInstance* g_thread_pool = nullptr;
23
GetDefaultMaxNumUtilityThreads(size_t max_num_foreground_threads_in)24 size_t GetDefaultMaxNumUtilityThreads(size_t max_num_foreground_threads_in) {
25 int num_of_efficient_processors = SysInfo::NumberOfEfficientProcessors();
26 if (num_of_efficient_processors != 0) {
27 DCHECK_GT(num_of_efficient_processors, 0);
28 return std::max<size_t>(
29 2, std::min(max_num_foreground_threads_in,
30 static_cast<size_t>(num_of_efficient_processors)));
31 }
32 return std::max<size_t>(2, max_num_foreground_threads_in / 2);
33 }
34
35 } // namespace
36
InitParams(size_t max_num_foreground_threads_in)37 ThreadPoolInstance::InitParams::InitParams(size_t max_num_foreground_threads_in)
38 : max_num_foreground_threads(max_num_foreground_threads_in),
39 max_num_utility_threads(
40 GetDefaultMaxNumUtilityThreads(max_num_foreground_threads_in)) {}
41
InitParams(size_t max_num_foreground_threads_in,size_t max_num_utility_threads_in)42 ThreadPoolInstance::InitParams::InitParams(size_t max_num_foreground_threads_in,
43 size_t max_num_utility_threads_in)
44 : max_num_foreground_threads(max_num_foreground_threads_in),
45 max_num_utility_threads(max_num_utility_threads_in) {}
46
47 ThreadPoolInstance::InitParams::~InitParams() = default;
48
ScopedExecutionFence()49 ThreadPoolInstance::ScopedExecutionFence::ScopedExecutionFence() {
50 DCHECK(g_thread_pool);
51 g_thread_pool->BeginFence();
52 }
53
~ScopedExecutionFence()54 ThreadPoolInstance::ScopedExecutionFence::~ScopedExecutionFence() {
55 DCHECK(g_thread_pool);
56 g_thread_pool->EndFence();
57 }
58
59 ThreadPoolInstance::ScopedBestEffortExecutionFence::
ScopedBestEffortExecutionFence()60 ScopedBestEffortExecutionFence() {
61 DCHECK(g_thread_pool);
62 g_thread_pool->BeginBestEffortFence();
63 }
64
65 ThreadPoolInstance::ScopedBestEffortExecutionFence::
~ScopedBestEffortExecutionFence()66 ~ScopedBestEffortExecutionFence() {
67 DCHECK(g_thread_pool);
68 g_thread_pool->EndBestEffortFence();
69 }
70
71 ThreadPoolInstance::ScopedFizzleBlockShutdownTasks::
ScopedFizzleBlockShutdownTasks()72 ScopedFizzleBlockShutdownTasks() {
73 // It's possible for this to be called without a ThreadPool present in tests.
74 if (g_thread_pool)
75 g_thread_pool->BeginFizzlingBlockShutdownTasks();
76 }
77
78 ThreadPoolInstance::ScopedFizzleBlockShutdownTasks::
~ScopedFizzleBlockShutdownTasks()79 ~ScopedFizzleBlockShutdownTasks() {
80 // It's possible for this to be called without a ThreadPool present in tests.
81 if (g_thread_pool)
82 g_thread_pool->EndFizzlingBlockShutdownTasks();
83 }
84
85 #if !BUILDFLAG(IS_NACL)
86 // static
CreateAndStartWithDefaultParams(StringPiece name)87 void ThreadPoolInstance::CreateAndStartWithDefaultParams(StringPiece name) {
88 Create(name);
89 g_thread_pool->StartWithDefaultParams();
90 }
91
StartWithDefaultParams()92 void ThreadPoolInstance::StartWithDefaultParams() {
93 // Values were chosen so that:
94 // * There are few background threads.
95 // * Background threads never outnumber foreground threads.
96 // * The system is utilized maximally by foreground threads.
97 // * The main thread is assumed to be busy, cap foreground workers at
98 // |num_cores - 1|.
99 const size_t max_num_foreground_threads =
100 static_cast<size_t>(std::max(3, SysInfo::NumberOfProcessors() - 1));
101 Start({max_num_foreground_threads});
102 }
103 #endif // !BUILDFLAG(IS_NACL)
104
Create(StringPiece name)105 void ThreadPoolInstance::Create(StringPiece name) {
106 Set(std::make_unique<internal::ThreadPoolImpl>(name));
107 }
108
109 // static
Set(std::unique_ptr<ThreadPoolInstance> thread_pool)110 void ThreadPoolInstance::Set(std::unique_ptr<ThreadPoolInstance> thread_pool) {
111 delete g_thread_pool;
112 g_thread_pool = thread_pool.release();
113 }
114
115 // static
Get()116 ThreadPoolInstance* ThreadPoolInstance::Get() {
117 return g_thread_pool;
118 }
119
120 } // namespace base
121