1 // Copyright 2017 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_SCHEDULER_SINGLE_THREAD_TASK_RUNNER_MANAGER_H_
6 #define BASE_TASK_SCHEDULER_SCHEDULER_SINGLE_THREAD_TASK_RUNNER_MANAGER_H_
7 
8 #include <memory>
9 #include <string>
10 #include <vector>
11 
12 #include "base/base_export.h"
13 #include "base/macros.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/task_scheduler/environment_config.h"
16 #include "base/task_scheduler/scheduler_lock.h"
17 #include "base/task_scheduler/single_thread_task_runner_thread_mode.h"
18 #include "base/task_scheduler/tracked_ref.h"
19 #include "base/threading/platform_thread.h"
20 #include "build/build_config.h"
21 
22 namespace base {
23 
24 class TaskTraits;
25 class SchedulerWorkerObserver;
26 class SingleThreadTaskRunner;
27 
28 namespace internal {
29 
30 class DelayedTaskManager;
31 class SchedulerWorker;
32 class TaskTracker;
33 
34 namespace {
35 
36 class SchedulerWorkerDelegate;
37 
38 }  // namespace
39 
40 // Manages a pool of threads which are each associated with one or more
41 // SingleThreadTaskRunners.
42 //
43 // SingleThreadTaskRunners using SingleThreadTaskRunnerThreadMode::SHARED are
44 // backed by shared SchedulerWorkers for each COM+task environment combination.
45 // These workers are lazily instantiated and then only reclaimed during
46 // JoinForTesting()
47 //
48 // No threads are created (and hence no tasks can run) before Start() is called.
49 //
50 // This class is thread-safe.
51 class BASE_EXPORT SchedulerSingleThreadTaskRunnerManager final {
52  public:
53   SchedulerSingleThreadTaskRunnerManager(
54       TrackedRef<TaskTracker> task_tracker,
55       DelayedTaskManager* delayed_task_manager);
56   ~SchedulerSingleThreadTaskRunnerManager();
57 
58   // Starts threads for existing SingleThreadTaskRunners and allows threads to
59   // be started when SingleThreadTaskRunners are created in the future. If
60   // specified, |scheduler_worker_observer| will be notified when a worker
61   // enters and exits its main function. It must not be destroyed before
62   // JoinForTesting() has returned (must never be destroyed in production).
63   void Start(SchedulerWorkerObserver* scheduler_worker_observer = nullptr);
64 
65   // Creates a SingleThreadTaskRunner which runs tasks with |traits| on a thread
66   // named "TaskSchedulerSingleThread[Shared]" +
67   // kEnvironmentParams[GetEnvironmentIndexForTraits(traits)].name_suffix +
68   // index.
69   scoped_refptr<SingleThreadTaskRunner> CreateSingleThreadTaskRunnerWithTraits(
70       const TaskTraits& traits,
71       SingleThreadTaskRunnerThreadMode thread_mode);
72 
73 #if defined(OS_WIN)
74   // Creates a SingleThreadTaskRunner which runs tasks with |traits| on a COM
75   // STA thread named "TaskSchedulerSingleThreadCOMSTA[Shared]" +
76   // kEnvironmentParams[GetEnvironmentIndexForTraits(traits)].name_suffix +
77   // index.
78   scoped_refptr<SingleThreadTaskRunner> CreateCOMSTATaskRunnerWithTraits(
79       const TaskTraits& traits,
80       SingleThreadTaskRunnerThreadMode thread_mode);
81 #endif  // defined(OS_WIN)
82 
83   void JoinForTesting();
84 
85  private:
86   class SchedulerSingleThreadTaskRunner;
87 
88   enum ContinueOnShutdown {
89     IS_CONTINUE_ON_SHUTDOWN,
90     IS_NOT_CONTINUE_ON_SHUTDOWN,
91     CONTINUE_ON_SHUTDOWN_COUNT,
92   };
93 
94   static ContinueOnShutdown TraitsToContinueOnShutdown(
95       const TaskTraits& traits);
96 
97   template <typename DelegateType>
98   scoped_refptr<SchedulerSingleThreadTaskRunner> CreateTaskRunnerWithTraitsImpl(
99       const TaskTraits& traits,
100       SingleThreadTaskRunnerThreadMode thread_mode);
101 
102   template <typename DelegateType>
103   std::unique_ptr<SchedulerWorkerDelegate> CreateSchedulerWorkerDelegate(
104       const std::string& name,
105       int id,
106       SingleThreadTaskRunnerThreadMode thread_mode);
107 
108   template <typename DelegateType>
109   SchedulerWorker* CreateAndRegisterSchedulerWorker(
110       const std::string& name,
111       SingleThreadTaskRunnerThreadMode thread_mode,
112       ThreadPriority priority_hint);
113 
114   template <typename DelegateType>
115   SchedulerWorker*& GetSharedSchedulerWorkerForTraits(const TaskTraits& traits);
116 
117   void UnregisterSchedulerWorker(SchedulerWorker* worker);
118 
119   void ReleaseSharedSchedulerWorkers();
120 
121   const TrackedRef<TaskTracker> task_tracker_;
122   DelayedTaskManager* const delayed_task_manager_;
123 
124   // Optional observer notified when a worker enters and exits its main
125   // function. Set in Start() and never modified afterwards.
126   SchedulerWorkerObserver* scheduler_worker_observer_ = nullptr;
127 
128   // Synchronizes access to all members below.
129   SchedulerLock lock_;
130   std::vector<scoped_refptr<SchedulerWorker>> workers_;
131   int next_worker_id_ = 0;
132 
133   // Workers for SingleThreadTaskRunnerThreadMode::SHARED tasks. It is
134   // important to have separate threads for CONTINUE_ON_SHUTDOWN and non-
135   // CONTINUE_ON_SHUTDOWN to avoid being in a situation where a
136   // CONTINUE_ON_SHUTDOWN task effectively blocks shutdown by preventing a
137   // BLOCK_SHUTDOWN task to be scheduled. https://crbug.com/829786
138   SchedulerWorker* shared_scheduler_workers_[ENVIRONMENT_COUNT]
139                                             [CONTINUE_ON_SHUTDOWN_COUNT] = {};
140 #if defined(OS_WIN)
141   SchedulerWorker* shared_com_scheduler_workers_[ENVIRONMENT_COUNT]
142                                                 [CONTINUE_ON_SHUTDOWN_COUNT] =
143                                                     {};
144 #endif  // defined(OS_WIN)
145 
146   // Set to true when Start() is called.
147   bool started_ = false;
148 
149   DISALLOW_COPY_AND_ASSIGN(SchedulerSingleThreadTaskRunnerManager);
150 };
151 
152 }  // namespace internal
153 }  // namespace base
154 
155 #endif  // BASE_TASK_SCHEDULER_SCHEDULER_SINGLE_THREAD_TASK_RUNNER_MANAGER_H_
156