Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: base/task_scheduler/scheduler_worker_pool_impl.h

Issue 2116163002: Add Lazy Creation and Thread Detachment Support in the Scheduler Worker Pool (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Test Controlled Detachment and Some Cleanup Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_TASK_SCHEDULER_SCHEDULER_WORKER_POOL_IMPL_H_ 5 #ifndef BASE_TASK_SCHEDULER_SCHEDULER_WORKER_POOL_IMPL_H_
6 #define BASE_TASK_SCHEDULER_SCHEDULER_WORKER_POOL_IMPL_H_ 6 #define BASE_TASK_SCHEDULER_SCHEDULER_WORKER_POOL_IMPL_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include <memory> 10 #include <memory>
(...skipping 12 matching lines...) Expand all
23 #include "base/task_scheduler/scheduler_lock.h" 23 #include "base/task_scheduler/scheduler_lock.h"
24 #include "base/task_scheduler/scheduler_worker.h" 24 #include "base/task_scheduler/scheduler_worker.h"
25 #include "base/task_scheduler/scheduler_worker_pool.h" 25 #include "base/task_scheduler/scheduler_worker_pool.h"
26 #include "base/task_scheduler/scheduler_worker_stack.h" 26 #include "base/task_scheduler/scheduler_worker_stack.h"
27 #include "base/task_scheduler/sequence.h" 27 #include "base/task_scheduler/sequence.h"
28 #include "base/task_scheduler/task.h" 28 #include "base/task_scheduler/task.h"
29 #include "base/task_scheduler/task_traits.h" 29 #include "base/task_scheduler/task_traits.h"
30 #include "base/threading/platform_thread.h" 30 #include "base/threading/platform_thread.h"
31 31
32 namespace base { 32 namespace base {
33
34 class TimeDelta;
35
33 namespace internal { 36 namespace internal {
34 37
35 class DelayedTaskManager; 38 class DelayedTaskManager;
36 class TaskTracker; 39 class TaskTracker;
37 40
38 // A pool of workers that run Tasks. This class is thread-safe. 41 // A pool of workers that run Tasks. This class is thread-safe.
39 class BASE_EXPORT SchedulerWorkerPoolImpl : public SchedulerWorkerPool { 42 class BASE_EXPORT SchedulerWorkerPoolImpl : public SchedulerWorkerPool {
40 public: 43 public:
41 enum class IORestriction { 44 enum class IORestriction {
42 ALLOWED, 45 ALLOWED,
43 DISALLOWED, 46 DISALLOWED,
44 }; 47 };
45 48
46 // Callback invoked when a Sequence isn't empty after a worker pops a Task 49 // Callback invoked when a Sequence isn't empty after a worker pops a Task
47 // from it. 50 // from it.
48 using ReEnqueueSequenceCallback = Callback<void(scoped_refptr<Sequence>)>; 51 using ReEnqueueSequenceCallback = Callback<void(scoped_refptr<Sequence>)>;
49 52
50 // Destroying a SchedulerWorkerPoolImpl returned by Create() is not allowed in 53 // Destroying a SchedulerWorkerPoolImpl returned by Create() is not allowed in
51 // production; it is always leaked. In tests, it can only be destroyed after 54 // production; it is always leaked. In tests, it can only be destroyed after
52 // JoinForTesting() has returned. 55 // JoinForTesting() has returned.
53 ~SchedulerWorkerPoolImpl() override; 56 ~SchedulerWorkerPoolImpl() override;
54 57
55 // Creates a SchedulerWorkerPoolImpl labeled |name| with up to |max_threads| 58 // Creates a SchedulerWorkerPoolImpl labeled |name| with up to |max_threads|
56 // threads of priority |thread_priority|. |io_restriction| indicates whether 59 // threads of priority |thread_priority|. |io_restriction| indicates whether
57 // Tasks on the constructed worker pool are allowed to make I/O calls. 60 // Tasks on the constructed worker pool are allowed to make I/O calls.
58 // |re_enqueue_sequence_callback| will be invoked after a worker of this 61 // |suggested_reclaim_time| sets a suggestion on when to reclaim idle threads.
59 // worker pool tries to run a Task. |task_tracker| is used to handle shutdown 62 // The worker pool is free to ignore this value for performance or correctness
60 // behavior of Tasks. |delayed_task_manager| handles Tasks posted with a 63 // reasons. |re_enqueue_sequence_callback| will be invoked after a worker of
61 // delay. Returns nullptr on failure to create a worker pool with at least one 64 // this worker pool tries to run a Task. |task_tracker| is used to handle
62 // thread. 65 // shutdown behavior of Tasks. |delayed_task_manager| handles Tasks posted
66 // with a delay. Returns nullptr on failure to create a worker pool with at
67 // least one thread.
63 static std::unique_ptr<SchedulerWorkerPoolImpl> Create( 68 static std::unique_ptr<SchedulerWorkerPoolImpl> Create(
64 StringPiece name, 69 StringPiece name,
65 ThreadPriority thread_priority, 70 ThreadPriority thread_priority,
66 size_t max_threads, 71 size_t max_threads,
67 IORestriction io_restriction, 72 IORestriction io_restriction,
73 const TimeDelta& suggested_reclaim_time,
68 const ReEnqueueSequenceCallback& re_enqueue_sequence_callback, 74 const ReEnqueueSequenceCallback& re_enqueue_sequence_callback,
69 TaskTracker* task_tracker, 75 TaskTracker* task_tracker,
70 DelayedTaskManager* delayed_task_manager); 76 DelayedTaskManager* delayed_task_manager);
71 77
72 // Waits until all workers are idle. 78 // Waits until all workers are idle.
73 void WaitForAllWorkersIdleForTesting(); 79 void WaitForAllWorkersIdleForTesting();
74 80
75 // Joins all workers of this worker pool. Tasks that are already running are 81 // Joins all workers of this worker pool. Tasks that are already running are
76 // allowed to complete their execution. This can only be called once. 82 // allowed to complete their execution. This can only be called once.
77 void JoinForTesting(); 83 void JoinForTesting();
78 84
85 // Disallows worker thread detachment. It's recommended that this should be
86 // called before dispatching the first set of work to avoid detach and join
87 // races.
88 void DisallowWorkerDetachmentForTesting();
gab 2016/07/13 18:36:31 It seems weird to me that something that is "recom
robliao 2016/07/13 20:19:47 I've amended the comment. Tests that specify a rec
89
79 // SchedulerWorkerPool: 90 // SchedulerWorkerPool:
80 scoped_refptr<TaskRunner> CreateTaskRunnerWithTraits( 91 scoped_refptr<TaskRunner> CreateTaskRunnerWithTraits(
81 const TaskTraits& traits, 92 const TaskTraits& traits,
82 ExecutionMode execution_mode) override; 93 ExecutionMode execution_mode) override;
83 void ReEnqueueSequence(scoped_refptr<Sequence> sequence, 94 void ReEnqueueSequence(scoped_refptr<Sequence> sequence,
84 const SequenceSortKey& sequence_sort_key) override; 95 const SequenceSortKey& sequence_sort_key) override;
85 bool PostTaskWithSequence(std::unique_ptr<Task> task, 96 bool PostTaskWithSequence(std::unique_ptr<Task> task,
86 scoped_refptr<Sequence> sequence, 97 scoped_refptr<Sequence> sequence,
87 SchedulerWorker* worker) override; 98 SchedulerWorker* worker) override;
88 void PostTaskWithSequenceNow(std::unique_ptr<Task> task, 99 void PostTaskWithSequenceNow(std::unique_ptr<Task> task,
89 scoped_refptr<Sequence> sequence, 100 scoped_refptr<Sequence> sequence,
90 SchedulerWorker* worker) override; 101 SchedulerWorker* worker) override;
91 102
92 private: 103 private:
104 class SchedulerSingleThreadTaskRunner;
93 class SchedulerWorkerDelegateImpl; 105 class SchedulerWorkerDelegateImpl;
94 106
95 SchedulerWorkerPoolImpl(StringPiece name, 107 SchedulerWorkerPoolImpl(StringPiece name,
96 IORestriction io_restriction, 108 IORestriction io_restriction,
109 const TimeDelta& suggested_reclaim_time,
97 TaskTracker* task_tracker, 110 TaskTracker* task_tracker,
98 DelayedTaskManager* delayed_task_manager); 111 DelayedTaskManager* delayed_task_manager);
99 112
100 bool Initialize( 113 bool Initialize(
101 ThreadPriority thread_priority, 114 ThreadPriority thread_priority,
102 size_t max_threads, 115 size_t max_threads,
103 const ReEnqueueSequenceCallback& re_enqueue_sequence_callback); 116 const ReEnqueueSequenceCallback& re_enqueue_sequence_callback);
104 117
105 // Wakes up the last worker from this worker pool to go idle, if any. 118 // Wakes up the last worker from this worker pool to go idle, if any.
106 void WakeUpOneWorker(); 119 void WakeUpOneWorker();
107 120
108 // Adds |worker| to |idle_workers_stack_|. 121 // Adds |worker| to |idle_workers_stack_|.
109 void AddToIdleWorkersStack(SchedulerWorker* worker); 122 void AddToIdleWorkersStack(SchedulerWorker* worker);
110 123
124 // Peeks from |idle_workers_stack_|.
125 const SchedulerWorker* PeekAtIdleWorkersStack() const;
126
111 // Removes |worker| from |idle_workers_stack_|. 127 // Removes |worker| from |idle_workers_stack_|.
112 void RemoveFromIdleWorkersStack(SchedulerWorker* worker); 128 void RemoveFromIdleWorkersStack(SchedulerWorker* worker);
113 129
130 // Returns true if worker thread detachment is permitted.
131 bool CanWorkerDetachForTesting();
132
114 // The name of this worker pool, used to label its worker threads. 133 // The name of this worker pool, used to label its worker threads.
115 const std::string name_; 134 const std::string name_;
116 135
117 // All worker owned by this worker pool. Only modified during initialization 136 // All worker owned by this worker pool. Only modified during initialization
118 // of the worker pool. 137 // of the worker pool.
119 std::vector<std::unique_ptr<SchedulerWorker>> workers_; 138 std::vector<std::unique_ptr<SchedulerWorker>> workers_;
120 139
121 // Synchronizes access to |next_worker_index_|. 140 // Synchronizes access to |next_worker_index_|.
122 SchedulerLock next_worker_index_lock_; 141 SchedulerLock next_worker_index_lock_;
123 142
124 // Index of the worker that will be assigned to the next single-threaded 143 // Index of the worker that will be assigned to the next single-threaded
125 // TaskRunner returned by this pool. 144 // TaskRunner returned by this pool.
126 size_t next_worker_index_ = 0; 145 size_t next_worker_index_ = 0;
127 146
128 // PriorityQueue from which all threads of this worker pool get work. 147 // PriorityQueue from which all threads of this worker pool get work.
129 PriorityQueue shared_priority_queue_; 148 PriorityQueue shared_priority_queue_;
130 149
131 // Indicates whether Tasks on this worker pool are allowed to make I/O calls. 150 // Indicates whether Tasks on this worker pool are allowed to make I/O calls.
132 const IORestriction io_restriction_; 151 const IORestriction io_restriction_;
133 152
153 // Suggested reclaim time for workers.
154 const TimeDelta suggested_reclaim_time_;
155
134 // Synchronizes access to |idle_workers_stack_| and 156 // Synchronizes access to |idle_workers_stack_| and
135 // |idle_workers_stack_cv_for_testing_|. Has |shared_priority_queue_|'s 157 // |idle_workers_stack_cv_for_testing_|. Has |shared_priority_queue_|'s
136 // lock as its predecessor so that a worker can be pushed to 158 // lock as its predecessor so that a worker can be pushed to
137 // |idle_workers_stack_| within the scope of a Transaction (more 159 // |idle_workers_stack_| within the scope of a Transaction (more
138 // details in GetWork()). 160 // details in GetWork()).
139 SchedulerLock idle_workers_stack_lock_; 161 mutable SchedulerLock idle_workers_stack_lock_;
140 162
141 // Stack of idle workers. 163 // Stack of idle workers.
142 SchedulerWorkerStack idle_workers_stack_; 164 SchedulerWorkerStack idle_workers_stack_;
143 165
144 // Signaled when all workers become idle. 166 // Signaled when all workers become idle.
145 std::unique_ptr<ConditionVariable> idle_workers_stack_cv_for_testing_; 167 std::unique_ptr<ConditionVariable> idle_workers_stack_cv_for_testing_;
146 168
147 // Signaled once JoinForTesting() has returned. 169 // Signaled once JoinForTesting() has returned.
148 WaitableEvent join_for_testing_returned_; 170 WaitableEvent join_for_testing_returned_;
149 171
172 // Synchronizes access to |worker_detachment_allowed_|.
173 SchedulerLock worker_detachment_allowed_lock_;
174
175 // Indicates to the delegates that workers are permitted to detach their
176 // threads.
177 bool worker_detachment_allowed_;
gab 2016/07/13 18:36:31 Use a manual WaitableEvent instead of bool + lock?
robliao 2016/07/13 20:19:47 Discussed here: https://codereview.chromium.org/21
178
150 #if DCHECK_IS_ON() 179 #if DCHECK_IS_ON()
151 // Signaled when all workers have been created. 180 // Signaled when all workers have been created.
152 WaitableEvent workers_created_; 181 WaitableEvent workers_created_;
153 #endif 182 #endif
154 183
155 TaskTracker* const task_tracker_; 184 TaskTracker* const task_tracker_;
156 DelayedTaskManager* const delayed_task_manager_; 185 DelayedTaskManager* const delayed_task_manager_;
157 186
158 DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerPoolImpl); 187 DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerPoolImpl);
159 }; 188 };
160 189
161 } // namespace internal 190 } // namespace internal
162 } // namespace base 191 } // namespace base
163 192
164 #endif // BASE_TASK_SCHEDULER_SCHEDULER_WORKER_POOL_IMPL_H_ 193 #endif // BASE_TASK_SCHEDULER_SCHEDULER_WORKER_POOL_IMPL_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698