fdoray | 4151cea | 2016-05-06 15:39:14 | [diff] [blame] | 1 | // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Gabriel Charette | 52fa3ae | 2019-04-15 21:44:37 | [diff] [blame] | 5 | #ifndef BASE_TASK_THREAD_POOL_THREAD_POOL_IMPL_H_ |
| 6 | #define BASE_TASK_THREAD_POOL_THREAD_POOL_IMPL_H_ |
fdoray | 4151cea | 2016-05-06 15:39:14 | [diff] [blame] | 7 | |
| 8 | #include <memory> |
fdoray | 51da6a83 | 2016-06-28 22:51:08 | [diff] [blame] | 9 | #include <vector> |
fdoray | 4151cea | 2016-05-06 15:39:14 | [diff] [blame] | 10 | |
| 11 | #include "base/base_export.h" |
fdoray | 51da6a83 | 2016-06-28 22:51:08 | [diff] [blame] | 12 | #include "base/callback.h" |
fdoray | 4151cea | 2016-05-06 15:39:14 | [diff] [blame] | 13 | #include "base/logging.h" |
| 14 | #include "base/macros.h" |
fdoray | b199f1be | 2017-05-29 23:00:03 | [diff] [blame] | 15 | #include "base/memory/ptr_util.h" |
fdoray | 4151cea | 2016-05-06 15:39:14 | [diff] [blame] | 16 | #include "base/memory/ref_counted.h" |
Gabriel Charette | 1b3b02a | 2019-07-11 02:58:16 | [diff] [blame] | 17 | #include "base/optional.h" |
Etienne Pierre-doray | efad3ec | 2019-04-17 17:07:05 | [diff] [blame] | 18 | #include "base/sequence_checker.h" |
fdoray | 5d16e80 | 2017-04-19 14:45:16 | [diff] [blame] | 19 | #include "base/strings/string_piece.h" |
fdoray | ef19112 | 2016-07-25 14:43:17 | [diff] [blame] | 20 | #include "base/synchronization/atomic_flag.h" |
Gabriel Charette | 04b138f | 2018-08-06 00:03:22 | [diff] [blame] | 21 | #include "base/task/single_thread_task_runner_thread_mode.h" |
Gabriel Charette | 43fd370 | 2019-05-29 16:36:51 | [diff] [blame] | 22 | #include "base/task/task_executor.h" |
Gabriel Charette | 04b138f | 2018-08-06 00:03:22 | [diff] [blame] | 23 | #include "base/task/task_traits.h" |
Gabriel Charette | 52fa3ae | 2019-04-15 21:44:37 | [diff] [blame] | 24 | #include "base/task/thread_pool/delayed_task_manager.h" |
| 25 | #include "base/task/thread_pool/environment_config.h" |
Gabriel Charette | 3e2898f | 2019-05-01 14:55:01 | [diff] [blame] | 26 | #include "base/task/thread_pool/pooled_single_thread_task_runner_manager.h" |
| 27 | #include "base/task/thread_pool/pooled_task_runner_delegate.h" |
Etienne Pierre-doray | abfecf7 | 2019-05-09 20:41:48 | [diff] [blame] | 28 | #include "base/task/thread_pool/task_source.h" |
Gabriel Charette | 52fa3ae | 2019-04-15 21:44:37 | [diff] [blame] | 29 | #include "base/task/thread_pool/task_tracker.h" |
Gabriel Charette | 3e2898f | 2019-05-01 14:55:01 | [diff] [blame] | 30 | #include "base/task/thread_pool/thread_group.h" |
| 31 | #include "base/task/thread_pool/thread_group_impl.h" |
Gabriel Charette | eadf5886 | 2019-08-29 05:20:27 | [diff] [blame] | 32 | #include "base/task/thread_pool/thread_pool_instance.h" |
Jesse McKenna | 0007454 | 2018-11-30 02:08:09 | [diff] [blame] | 33 | #include "base/updateable_sequenced_task_runner.h" |
robliao | 75dd50b | 2017-03-29 17:11:17 | [diff] [blame] | 34 | #include "build/build_config.h" |
fdoray | 4151cea | 2016-05-06 15:39:14 | [diff] [blame] | 35 | |
fdoray | 2cc05d1 | 2017-04-19 14:06:54 | [diff] [blame] | 36 | #if defined(OS_POSIX) && !defined(OS_NACL_SFI) |
Gabriel Charette | 52fa3ae | 2019-04-15 21:44:37 | [diff] [blame] | 37 | #include "base/task/thread_pool/task_tracker_posix.h" |
fdoray | 2cc05d1 | 2017-04-19 14:06:54 | [diff] [blame] | 38 | #endif |
| 39 | |
Robert Liao | dd04109f | 2017-06-27 22:05:37 | [diff] [blame] | 40 | #if defined(OS_WIN) |
| 41 | #include "base/win/com_init_check_hook.h" |
| 42 | #endif |
| 43 | |
fdoray | 4151cea | 2016-05-06 15:39:14 | [diff] [blame] | 44 | namespace base { |
robliao | 5a36369 | 2016-08-01 22:29:05 | [diff] [blame] | 45 | |
Gabriel Charette | 6084a13 | 2018-05-04 19:05:59 | [diff] [blame] | 46 | class Thread; |
robliao | 5a36369 | 2016-08-01 22:29:05 | [diff] [blame] | 47 | |
fdoray | 4151cea | 2016-05-06 15:39:14 | [diff] [blame] | 48 | namespace internal { |
| 49 | |
Gabriel Charette | 43fd370 | 2019-05-29 16:36:51 | [diff] [blame] | 50 | // Default ThreadPoolInstance implementation. This class is thread-safe. |
| 51 | class BASE_EXPORT ThreadPoolImpl : public ThreadPoolInstance, |
| 52 | public TaskExecutor, |
Gabriel Charette | 3e2898f | 2019-05-01 14:55:01 | [diff] [blame] | 53 | public ThreadGroup::Delegate, |
| 54 | public PooledTaskRunnerDelegate { |
fdoray | 4151cea | 2016-05-06 15:39:14 | [diff] [blame] | 55 | public: |
fdoray | b199f1be | 2017-05-29 23:00:03 | [diff] [blame] | 56 | using TaskTrackerImpl = |
| 57 | #if defined(OS_POSIX) && !defined(OS_NACL_SFI) |
| 58 | TaskTrackerPosix; |
| 59 | #else |
| 60 | TaskTracker; |
| 61 | #endif |
| 62 | |
Francois Doray | 098076d | 2019-10-25 21:04:57 | [diff] [blame] | 63 | // Creates a ThreadPoolImpl with a production TaskTracker. |histogram_label| |
| 64 | // is used to label histograms. No histograms are recorded if it is empty. |
Gabriel Charette | 52fa3ae | 2019-04-15 21:44:37 | [diff] [blame] | 65 | explicit ThreadPoolImpl(StringPiece histogram_label); |
Gabriel Charette | 19621cd | 2018-01-18 16:48:59 | [diff] [blame] | 66 | |
Gabriel Charette | 996000b | 2019-08-14 23:41:19 | [diff] [blame] | 67 | // For testing only. Creates a ThreadPoolImpl with a custom TaskTracker. |
Gabriel Charette | 52fa3ae | 2019-04-15 21:44:37 | [diff] [blame] | 68 | ThreadPoolImpl(StringPiece histogram_label, |
Gabriel Charette | 996000b | 2019-08-14 23:41:19 | [diff] [blame] | 69 | std::unique_ptr<TaskTrackerImpl> task_tracker); |
Gabriel Charette | 19621cd | 2018-01-18 16:48:59 | [diff] [blame] | 70 | |
Gabriel Charette | 52fa3ae | 2019-04-15 21:44:37 | [diff] [blame] | 71 | ~ThreadPoolImpl() override; |
fdoray | 4151cea | 2016-05-06 15:39:14 | [diff] [blame] | 72 | |
Gabriel Charette | 43fd370 | 2019-05-29 16:36:51 | [diff] [blame] | 73 | // ThreadPoolInstance: |
| 74 | void Start(const ThreadPoolInstance::InitParams& init_params, |
Gabriel Charette | 3e2898f | 2019-05-01 14:55:01 | [diff] [blame] | 75 | WorkerThreadObserver* worker_thread_observer) override; |
Eric Seckler | cdd866d | 2018-08-21 10:49:54 | [diff] [blame] | 76 | int GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated( |
| 77 | const TaskTraits& traits) const override; |
| 78 | void Shutdown() override; |
| 79 | void FlushForTesting() override; |
| 80 | void FlushAsyncForTesting(OnceClosure flush_callback) override; |
| 81 | void JoinForTesting() override; |
Francois Doray | c92dedd2 | 2019-11-01 13:48:54 | [diff] [blame] | 82 | void BeginFence() override; |
| 83 | void EndFence() override; |
| 84 | void BeginBestEffortFence() override; |
| 85 | void EndBestEffortFence() override; |
Eric Seckler | cdd866d | 2018-08-21 10:49:54 | [diff] [blame] | 86 | |
| 87 | // TaskExecutor: |
Sami Kyostila | 675d7dc9 | 2019-06-05 10:33:08 | [diff] [blame] | 88 | bool PostDelayedTask(const Location& from_here, |
| 89 | const TaskTraits& traits, |
| 90 | OnceClosure task, |
| 91 | TimeDelta delay) override; |
| 92 | scoped_refptr<TaskRunner> CreateTaskRunner(const TaskTraits& traits) override; |
| 93 | scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunner( |
fdoray | e72adfa1 | 2016-11-02 14:35:26 | [diff] [blame] | 94 | const TaskTraits& traits) override; |
Sami Kyostila | 675d7dc9 | 2019-06-05 10:33:08 | [diff] [blame] | 95 | scoped_refptr<SingleThreadTaskRunner> CreateSingleThreadTaskRunner( |
robliao | 94520d7 | 2017-05-12 12:43:35 | [diff] [blame] | 96 | const TaskTraits& traits, |
| 97 | SingleThreadTaskRunnerThreadMode thread_mode) override; |
robliao | 75dd50b | 2017-03-29 17:11:17 | [diff] [blame] | 98 | #if defined(OS_WIN) |
Sami Kyostila | 675d7dc9 | 2019-06-05 10:33:08 | [diff] [blame] | 99 | scoped_refptr<SingleThreadTaskRunner> CreateCOMSTATaskRunner( |
robliao | 94520d7 | 2017-05-12 12:43:35 | [diff] [blame] | 100 | const TaskTraits& traits, |
| 101 | SingleThreadTaskRunnerThreadMode thread_mode) override; |
robliao | 75dd50b | 2017-03-29 17:11:17 | [diff] [blame] | 102 | #endif // defined(OS_WIN) |
Alex Clarke | 0dd49956 | 2019-10-18 19:45:09 | [diff] [blame] | 103 | const scoped_refptr<SequencedTaskRunner>& GetContinuationTaskRunner() |
| 104 | override; |
Jesse McKenna | 0007454 | 2018-11-30 02:08:09 | [diff] [blame] | 105 | scoped_refptr<UpdateableSequencedTaskRunner> |
Sami Kyostila | 675d7dc9 | 2019-06-05 10:33:08 | [diff] [blame] | 106 | CreateUpdateableSequencedTaskRunner(const TaskTraits& traits); |
fdoray | 4151cea | 2016-05-06 15:39:14 | [diff] [blame] | 107 | |
Etienne Pierre-doray | 38cb18ba | 2019-08-08 19:50:37 | [diff] [blame] | 108 | // PooledTaskRunnerDelegate: |
| 109 | bool EnqueueJobTaskSource(scoped_refptr<JobTaskSource> task_source) override; |
Etienne Pierre-doray | e62a138 | 2019-10-03 17:08:52 | [diff] [blame] | 110 | void RemoveJobTaskSource(scoped_refptr<JobTaskSource> task_source) override; |
Etienne Pierre-doray | ac368074 | 2019-08-29 17:43:17 | [diff] [blame] | 111 | void UpdatePriority(scoped_refptr<TaskSource> task_source, |
| 112 | TaskPriority priority) override; |
Etienne Pierre-doray | 38cb18ba | 2019-08-08 19:50:37 | [diff] [blame] | 113 | |
Gabriel Charette | 1b3b02a | 2019-07-11 02:58:16 | [diff] [blame] | 114 | // Returns the TimeTicks of the next task scheduled on ThreadPool (Now() if |
| 115 | // immediate, nullopt if none). This is thread-safe, i.e., it's safe if tasks |
| 116 | // are being posted in parallel with this call but such a situation obviously |
| 117 | // results in a race as to whether this call will see the new tasks in time. |
| 118 | Optional<TimeTicks> NextScheduledRunTimeForTesting() const; |
| 119 | |
| 120 | // Forces ripe delayed tasks to be posted (e.g. when time is mocked and |
| 121 | // advances faster than the real-time delay on ServiceThread). |
| 122 | void ProcessRipeDelayedTasksForTesting(); |
| 123 | |
fdoray | 4151cea | 2016-05-06 15:39:14 | [diff] [blame] | 124 | private: |
Francois Doray | c92dedd2 | 2019-11-01 13:48:54 | [diff] [blame] | 125 | // Invoked after |num_fences_| or |num_best_effort_fences_| is updated. Sets |
| 126 | // the CanRunPolicy in TaskTracker and wakes up workers as appropriate. |
Etienne Pierre-doray | efad3ec | 2019-04-17 17:07:05 | [diff] [blame] | 127 | void UpdateCanRunPolicy(); |
| 128 | |
Francois Doray | d9f7e1a | 2017-08-22 20:20:40 | [diff] [blame] | 129 | // Returns |traits|, with priority set to TaskPriority::USER_BLOCKING if |
| 130 | // |all_tasks_user_blocking_| is set. |
Francois Doray | 0ca4f565d | 2019-04-04 12:45:42 | [diff] [blame] | 131 | TaskTraits SetUserBlockingPriorityIfNeeded(TaskTraits traits) const; |
Francois Doray | d9f7e1a | 2017-08-22 20:20:40 | [diff] [blame] | 132 | |
Etienne Pierre-doray | 730a939 | 2018-08-13 22:39:31 | [diff] [blame] | 133 | void ReportHeartbeatMetrics() const; |
| 134 | |
Gabriel Charette | 3e2898f | 2019-05-01 14:55:01 | [diff] [blame] | 135 | const ThreadGroup* GetThreadGroupForTraits(const TaskTraits& traits) const; |
Aditya Keerthi | c174d337e | 2019-03-05 18:14:16 | [diff] [blame] | 136 | |
Gabriel Charette | 3e2898f | 2019-05-01 14:55:01 | [diff] [blame] | 137 | // ThreadGroup::Delegate: |
| 138 | ThreadGroup* GetThreadGroupForTraits(const TaskTraits& traits) override; |
Jesse McKenna | bcab5d9 | 2018-10-22 16:54:21 | [diff] [blame] | 139 | |
Etienne Pierre-doray | abfecf7 | 2019-05-09 20:41:48 | [diff] [blame] | 140 | // Posts |task| to be executed by the appropriate thread group as part of |
| 141 | // |sequence|. This must only be called after |task| has gone through |
| 142 | // TaskTracker::WillPostTask() and after |task|'s delayed run time. |
| 143 | bool PostTaskWithSequenceNow(Task task, scoped_refptr<Sequence> sequence); |
| 144 | |
Gabriel Charette | 3e2898f | 2019-05-01 14:55:01 | [diff] [blame] | 145 | // PooledTaskRunnerDelegate: |
Jesse McKenna | cf41806 | 2018-10-26 18:05:59 | [diff] [blame] | 146 | bool PostTaskWithSequence(Task task, |
| 147 | scoped_refptr<Sequence> sequence) override; |
Etienne Pierre-doray | d4d2481e | 2019-08-29 21:07:04 | [diff] [blame] | 148 | bool ShouldYield(const TaskSource* task_source) const override; |
Jesse McKenna | cf41806 | 2018-10-26 18:05:59 | [diff] [blame] | 149 | |
fdoray | b199f1be | 2017-05-29 23:00:03 | [diff] [blame] | 150 | const std::unique_ptr<TaskTrackerImpl> task_tracker_; |
Gabriel Charette | 3fb9e4f | 2018-05-18 21:34:43 | [diff] [blame] | 151 | std::unique_ptr<Thread> service_thread_; |
fdoray | 840441c | 2017-04-20 13:13:11 | [diff] [blame] | 152 | DelayedTaskManager delayed_task_manager_; |
Gabriel Charette | 3e2898f | 2019-05-01 14:55:01 | [diff] [blame] | 153 | PooledSingleThreadTaskRunnerManager single_thread_task_runner_manager_; |
fdoray | e7e8477 | 2017-04-19 13:42:24 | [diff] [blame] | 154 | |
Francois Doray | d9f7e1a | 2017-08-22 20:20:40 | [diff] [blame] | 155 | // Indicates that all tasks are handled as if they had been posted with |
| 156 | // TaskPriority::USER_BLOCKING. Since this is set in Start(), it doesn't apply |
| 157 | // to tasks posted before Start() or to tasks posted to TaskRunners created |
| 158 | // before Start(). |
Francois Doray | fbfcc6b | 2017-08-25 19:44:58 | [diff] [blame] | 159 | // |
| 160 | // TODO(fdoray): Remove after experiment. https://crbug.com/757022 |
Francois Doray | d9f7e1a | 2017-08-22 20:20:40 | [diff] [blame] | 161 | AtomicFlag all_tasks_user_blocking_; |
| 162 | |
Gabriel Charette | 60496c7 | 2019-05-02 15:54:41 | [diff] [blame] | 163 | std::unique_ptr<ThreadGroup> foreground_thread_group_; |
| 164 | std::unique_ptr<ThreadGroupImpl> background_thread_group_; |
robliao | 3d93b69 | 2016-05-12 18:27:15 | [diff] [blame] | 165 | |
Etienne Pierre-doray | efad3ec | 2019-04-17 17:07:05 | [diff] [blame] | 166 | // Whether this TaskScheduler was started. Access controlled by |
| 167 | // |sequence_checker_|. |
| 168 | bool started_ = false; |
| 169 | |
François Doray | 906d5f3 | 2019-05-29 21:00:46 | [diff] [blame] | 170 | // Whether the --disable-best-effort-tasks switch is preventing execution of |
| 171 | // BEST_EFFORT tasks until shutdown. |
| 172 | const bool has_disable_best_effort_switch_; |
| 173 | |
Francois Doray | c92dedd2 | 2019-11-01 13:48:54 | [diff] [blame] | 174 | // Number of fences preventing execution of tasks of any/BEST_EFFORT priority. |
| 175 | // Access controlled by |sequence_checker_|. |
| 176 | int num_fences_ = 0; |
| 177 | int num_best_effort_fences_ = 0; |
Etienne Pierre-doray | efad3ec | 2019-04-17 17:07:05 | [diff] [blame] | 178 | |
fdoray | 4151cea | 2016-05-06 15:39:14 | [diff] [blame] | 179 | #if DCHECK_IS_ON() |
fdoray | ef19112 | 2016-07-25 14:43:17 | [diff] [blame] | 180 | // Set once JoinForTesting() has returned. |
| 181 | AtomicFlag join_for_testing_returned_; |
fdoray | 4151cea | 2016-05-06 15:39:14 | [diff] [blame] | 182 | #endif |
| 183 | |
Robert Liao | dd04109f | 2017-06-27 22:05:37 | [diff] [blame] | 184 | #if defined(OS_WIN) && defined(COM_INIT_CHECK_HOOK_ENABLED) |
| 185 | // Provides COM initialization verification for supported builds. |
| 186 | base::win::ComInitCheckHook com_init_check_hook_; |
| 187 | #endif |
| 188 | |
Etienne Pierre-doray | efad3ec | 2019-04-17 17:07:05 | [diff] [blame] | 189 | // Asserts that operations occur in sequence with Start(). |
| 190 | SEQUENCE_CHECKER(sequence_checker_); |
| 191 | |
Gabriel Charette | 3e2898f | 2019-05-01 14:55:01 | [diff] [blame] | 192 | TrackedRefFactory<ThreadGroup::Delegate> tracked_ref_factory_; |
Jesse McKenna | bcab5d9 | 2018-10-22 16:54:21 | [diff] [blame] | 193 | |
Gabriel Charette | 52fa3ae | 2019-04-15 21:44:37 | [diff] [blame] | 194 | DISALLOW_COPY_AND_ASSIGN(ThreadPoolImpl); |
fdoray | 4151cea | 2016-05-06 15:39:14 | [diff] [blame] | 195 | }; |
| 196 | |
| 197 | } // namespace internal |
| 198 | } // namespace base |
| 199 | |
Gabriel Charette | 52fa3ae | 2019-04-15 21:44:37 | [diff] [blame] | 200 | #endif // BASE_TASK_THREAD_POOL_THREAD_POOL_IMPL_H_ |