• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
5 #ifndef BASE_TASK_SCHEDULER_TASK_SCHEDULER_H_
6 #define BASE_TASK_SCHEDULER_TASK_SCHEDULER_H_
7 
8 #include <memory>
9 #include <vector>
10 
11 #include "base/base_export.h"
12 #include "base/callback.h"
13 #include "base/gtest_prod_util.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/sequenced_task_runner.h"
16 #include "base/single_thread_task_runner.h"
17 #include "base/strings/string_piece.h"
18 #include "base/task_runner.h"
19 #include "base/task_scheduler/scheduler_worker_pool_params.h"
20 #include "base/task_scheduler/single_thread_task_runner_thread_mode.h"
21 #include "base/task_scheduler/task_traits.h"
22 #include "base/time/time.h"
23 #include "build/build_config.h"
24 
25 namespace gin {
26 class V8Platform;
27 }
28 
29 namespace content {
30 // Can't use the FRIEND_TEST_ALL_PREFIXES macro because the test is in a
31 // different namespace.
32 class BrowserMainLoopTest_CreateThreadsInSingleProcess_Test;
33 }  // namespace content
34 
35 namespace base {
36 
37 class HistogramBase;
38 class Location;
39 class SchedulerWorkerObserver;
40 
41 // Interface for a task scheduler and static methods to manage the instance used
42 // by the post_task.h API.
43 //
44 // The task scheduler doesn't create threads until Start() is called. Tasks can
45 // be posted at any time but will not run until after Start() is called.
46 //
47 // The instance methods of this class are thread-safe.
48 //
49 // Note: All base/task_scheduler users should go through post_task.h instead of
50 // TaskScheduler except for the one callsite per process which manages the
51 // process's instance.
52 class BASE_EXPORT TaskScheduler {
53  public:
54   struct BASE_EXPORT InitParams {
55     enum class SharedWorkerPoolEnvironment {
56       // Use the default environment (no environment).
57       DEFAULT,
58 #if defined(OS_WIN)
59       // Place the worker in a COM MTA.
60       COM_MTA,
61 #endif  // defined(OS_WIN)
62     };
63 
64     InitParams(
65         const SchedulerWorkerPoolParams& background_worker_pool_params_in,
66         const SchedulerWorkerPoolParams&
67             background_blocking_worker_pool_params_in,
68         const SchedulerWorkerPoolParams& foreground_worker_pool_params_in,
69         const SchedulerWorkerPoolParams&
70             foreground_blocking_worker_pool_params_in,
71         SharedWorkerPoolEnvironment shared_worker_pool_environment_in =
72             SharedWorkerPoolEnvironment::DEFAULT);
73     ~InitParams();
74 
75     SchedulerWorkerPoolParams background_worker_pool_params;
76     SchedulerWorkerPoolParams background_blocking_worker_pool_params;
77     SchedulerWorkerPoolParams foreground_worker_pool_params;
78     SchedulerWorkerPoolParams foreground_blocking_worker_pool_params;
79     SharedWorkerPoolEnvironment shared_worker_pool_environment;
80   };
81 
82   // Destroying a TaskScheduler is not allowed in production; it is always
83   // leaked. In tests, it should only be destroyed after JoinForTesting() has
84   // returned.
85   virtual ~TaskScheduler() = default;
86 
87   // Allows the task scheduler to create threads and run tasks following the
88   // |init_params| specification.
89   //
90   // If specified, |scheduler_worker_observer| will be notified when a worker
91   // enters and exits its main function. It must not be destroyed before
92   // JoinForTesting() has returned (must never be destroyed in production).
93   //
94   // CHECKs on failure.
95   virtual void Start(
96       const InitParams& init_params,
97       SchedulerWorkerObserver* scheduler_worker_observer = nullptr) = 0;
98 
99   // Posts |task| with a |delay| and specific |traits|. |delay| can be zero.
100   // For one off tasks that don't require a TaskRunner.
101   virtual void PostDelayedTaskWithTraits(const Location& from_here,
102                                          const TaskTraits& traits,
103                                          OnceClosure task,
104                                          TimeDelta delay) = 0;
105 
106   // Returns a TaskRunner whose PostTask invocations result in scheduling tasks
107   // using |traits|. Tasks may run in any order and in parallel.
108   virtual scoped_refptr<TaskRunner> CreateTaskRunnerWithTraits(
109       const TaskTraits& traits) = 0;
110 
111   // Returns a SequencedTaskRunner whose PostTask invocations result in
112   // scheduling tasks using |traits|. Tasks run one at a time in posting order.
113   virtual scoped_refptr<SequencedTaskRunner>
114   CreateSequencedTaskRunnerWithTraits(const TaskTraits& traits) = 0;
115 
116   // Returns a SingleThreadTaskRunner whose PostTask invocations result in
117   // scheduling tasks using |traits|. Tasks run on a single thread in posting
118   // order.
119   virtual scoped_refptr<SingleThreadTaskRunner>
120   CreateSingleThreadTaskRunnerWithTraits(
121       const TaskTraits& traits,
122       SingleThreadTaskRunnerThreadMode thread_mode) = 0;
123 
124 #if defined(OS_WIN)
125   // Returns a SingleThreadTaskRunner whose PostTask invocations result in
126   // scheduling tasks using |traits| in a COM Single-Threaded Apartment. Tasks
127   // run in the same Single-Threaded Apartment in posting order for the returned
128   // SingleThreadTaskRunner. There is not necessarily a one-to-one
129   // correspondence between SingleThreadTaskRunners and Single-Threaded
130   // Apartments. The implementation is free to share apartments or create new
131   // apartments as necessary. In either case, care should be taken to make sure
132   // COM pointers are not smuggled across apartments.
133   virtual scoped_refptr<SingleThreadTaskRunner>
134   CreateCOMSTATaskRunnerWithTraits(
135       const TaskTraits& traits,
136       SingleThreadTaskRunnerThreadMode thread_mode) = 0;
137 #endif  // defined(OS_WIN)
138 
139   // Returns a vector of all histograms available in this task scheduler.
140   virtual std::vector<const HistogramBase*> GetHistograms() const = 0;
141 
142   // Synchronously shuts down the scheduler. Once this is called, only tasks
143   // posted with the BLOCK_SHUTDOWN behavior will be run. When this returns:
144   // - All SKIP_ON_SHUTDOWN tasks that were already running have completed their
145   //   execution.
146   // - All posted BLOCK_SHUTDOWN tasks have completed their execution.
147   // - CONTINUE_ON_SHUTDOWN tasks might still be running.
148   // Note that an implementation can keep threads and other resources alive to
149   // support running CONTINUE_ON_SHUTDOWN after this returns. This can only be
150   // called once.
151   virtual void Shutdown() = 0;
152 
153   // Waits until there are no pending undelayed tasks. May be called in tests
154   // to validate that a condition is met after all undelayed tasks have run.
155   //
156   // Does not wait for delayed tasks. Waits for undelayed tasks posted from
157   // other threads during the call. Returns immediately when shutdown completes.
158   virtual void FlushForTesting() = 0;
159 
160   // Returns and calls |flush_callback| when there are no incomplete undelayed
161   // tasks. |flush_callback| may be called back on any thread and should not
162   // perform a lot of work. May be used when additional work on the current
163   // thread needs to be performed during a flush. Only one
164   // FlushAsyncForTesting() may be pending at any given time.
165   virtual void FlushAsyncForTesting(OnceClosure flush_callback) = 0;
166 
167   // Joins all threads. Tasks that are already running are allowed to complete
168   // their execution. This can only be called once. Using this task scheduler
169   // instance to create task runners or post tasks is not permitted during or
170   // after this call.
171   virtual void JoinForTesting() = 0;
172 
173 // CreateAndStartWithDefaultParams(), Create(), and SetInstance() register a
174 // TaskScheduler to handle tasks posted through the post_task.h API for this
175 // process.
176 //
177 // Processes that need to initialize TaskScheduler with custom params or that
178 // need to allow tasks to be posted before the TaskScheduler creates its
179 // threads should use Create() followed by Start(). Other processes can use
180 // CreateAndStartWithDefaultParams().
181 //
182 // A registered TaskScheduler is only deleted when a new TaskScheduler is
183 // registered. The last registered TaskScheduler is leaked on shutdown. The
184 // methods below must not be called when TaskRunners created by a previous
185 // TaskScheduler are still alive. The methods are not thread-safe; proper
186 // synchronization is required to use the post_task.h API after registering a
187 // new TaskScheduler.
188 
189 #if !defined(OS_NACL)
190   // Creates and starts a task scheduler using default params. |name| is used to
191   // label histograms, it must not be empty. It should identify the component
192   // that calls this. Start() is called by this method; it is invalid to call it
193   // again afterwards. CHECKs on failure. For tests, prefer
194   // base::test::ScopedTaskEnvironment (ensures isolation).
195   static void CreateAndStartWithDefaultParams(StringPiece name);
196 
197   // Same as CreateAndStartWithDefaultParams() but allows callers to split the
198   // Create() and StartWithDefaultParams() calls.
199   void StartWithDefaultParams();
200 #endif  // !defined(OS_NACL)
201 
202   // Creates a ready to start task scheduler. |name| is used to label
203   // histograms, it must not be empty. It should identify the component that
204   // creates the TaskScheduler. The task scheduler doesn't create threads until
205   // Start() is called. Tasks can be posted at any time but will not run until
206   // after Start() is called. For tests, prefer
207   // base::test::ScopedTaskEnvironment (ensures isolation).
208   static void Create(StringPiece name);
209 
210   // Registers |task_scheduler| to handle tasks posted through the post_task.h
211   // API for this process. For tests, prefer base::test::ScopedTaskEnvironment
212   // (ensures isolation).
213   static void SetInstance(std::unique_ptr<TaskScheduler> task_scheduler);
214 
215   // Retrieve the TaskScheduler set via SetInstance() or
216   // CreateAndSet(Simple|Default)TaskScheduler(). This should be used very
217   // rarely; most users of TaskScheduler should use the post_task.h API. In
218   // particular, refrain from doing
219   //   if (!TaskScheduler::GetInstance()) {
220   //     TaskScheduler::SetInstance(...);
221   //     base::PostTask(...);
222   //   }
223   // instead make sure to SetInstance() early in one determinstic place in the
224   // process' initialization phase.
225   // In doubt, consult with //base/task_scheduler/OWNERS.
226   static TaskScheduler* GetInstance();
227 
228  private:
229   friend class gin::V8Platform;
230   friend class content::BrowserMainLoopTest_CreateThreadsInSingleProcess_Test;
231 
232   // Returns the maximum number of non-single-threaded non-blocked tasks posted
233   // with |traits| that can run concurrently in this TaskScheduler. |traits|
234   // can't contain TaskPriority::BACKGROUND.
235   //
236   // Do not use this method. To process n items, post n tasks that each process
237   // 1 item rather than GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated()
238   // tasks that each process
239   // n/GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated() items.
240   //
241   // TODO(fdoray): Remove this method. https://crbug.com/687264
242   virtual int GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
243       const TaskTraits& traits) const = 0;
244 };
245 
246 }  // namespace base
247 
248 #endif  // BASE_TASK_SCHEDULER_TASK_SCHEDULER_H_
249