OLD | NEW |
---|---|
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_H_ | 5 #ifndef BASE_TASK_SCHEDULER_SCHEDULER_WORKER_H_ |
6 #define BASE_TASK_SCHEDULER_SCHEDULER_WORKER_H_ | 6 #define BASE_TASK_SCHEDULER_SCHEDULER_WORKER_H_ |
7 | 7 |
8 #include <memory> | 8 #include <memory> |
9 | 9 |
10 #include "base/base_export.h" | 10 #include "base/base_export.h" |
(...skipping 19 matching lines...) Expand all Loading... | |
30 // A SchedulerWorker starts out sleeping. It is woken up by a call to WakeUp(). | 30 // A SchedulerWorker starts out sleeping. It is woken up by a call to WakeUp(). |
31 // After a wake-up, a SchedulerWorker runs Tasks from Sequences returned by the | 31 // After a wake-up, a SchedulerWorker runs Tasks from Sequences returned by the |
32 // GetWork() method of its delegate as long as it doesn't return nullptr. It | 32 // GetWork() method of its delegate as long as it doesn't return nullptr. It |
33 // also periodically checks with its TaskTracker whether shutdown has completed | 33 // also periodically checks with its TaskTracker whether shutdown has completed |
34 // and exits when it has. | 34 // and exits when it has. |
35 // | 35 // |
36 // The worker is free to release and reallocate the platform thread with | 36 // The worker is free to release and reallocate the platform thread with |
37 // guidance from the delegate. | 37 // guidance from the delegate. |
38 // | 38 // |
39 // This class is thread-safe. | 39 // This class is thread-safe. |
40 class BASE_EXPORT SchedulerWorker { | 40 class BASE_EXPORT SchedulerWorker |
41 : public RefCountedThreadSafe<SchedulerWorker> { | |
41 public: | 42 public: |
42 // Delegate interface for SchedulerWorker. The methods are always called from | 43 // Delegate interface for SchedulerWorker. The methods are always called from |
43 // the thread managed by the SchedulerWorker instance. | 44 // the thread managed by the SchedulerWorker instance. |
44 class Delegate { | 45 class Delegate { |
45 public: | 46 public: |
46 virtual ~Delegate() = default; | 47 virtual ~Delegate() = default; |
47 | 48 |
48 // Called by a thread managed by |worker| when it enters its main function. | 49 // Called by a thread managed by |worker| when it enters its main function. |
49 // If a thread is recreated after detachment, |detach_duration| is the time | 50 // If a thread is recreated after detachment, |detach_duration| is the time |
50 // elapsed since detachment. Otherwise, if this is the first thread created | 51 // elapsed since detachment. Otherwise, if this is the first thread created |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 enum class InitialState { ALIVE, DETACHED }; | 90 enum class InitialState { ALIVE, DETACHED }; |
90 | 91 |
91 // Creates a SchedulerWorker that runs Tasks from Sequences returned by | 92 // Creates a SchedulerWorker that runs Tasks from Sequences returned by |
92 // |delegate|. |priority_hint| is the preferred thread priority; the actual | 93 // |delegate|. |priority_hint| is the preferred thread priority; the actual |
93 // thread priority depends on shutdown state and platform capabilities. | 94 // thread priority depends on shutdown state and platform capabilities. |
94 // |task_tracker| is used to handle shutdown behavior of Tasks. If | 95 // |task_tracker| is used to handle shutdown behavior of Tasks. If |
95 // |worker_state| is DETACHED, the thread will be created upon a WakeUp(). | 96 // |worker_state| is DETACHED, the thread will be created upon a WakeUp(). |
96 // Returns nullptr if creating the underlying platform thread fails during | 97 // Returns nullptr if creating the underlying platform thread fails during |
97 // Create(). |backward_compatibility| indicates whether backward compatibility | 98 // Create(). |backward_compatibility| indicates whether backward compatibility |
98 // is enabled. | 99 // is enabled. |
99 static std::unique_ptr<SchedulerWorker> Create( | 100 static scoped_refptr<SchedulerWorker> Create( |
100 ThreadPriority priority_hint, | 101 ThreadPriority priority_hint, |
101 std::unique_ptr<Delegate> delegate, | 102 std::unique_ptr<Delegate> delegate, |
102 TaskTracker* task_tracker, | 103 TaskTracker* task_tracker, |
103 InitialState initial_state, | 104 InitialState initial_state, |
104 SchedulerBackwardCompatibility backward_compatibility = | 105 SchedulerBackwardCompatibility backward_compatibility = |
105 SchedulerBackwardCompatibility::DISABLED); | 106 SchedulerBackwardCompatibility::DISABLED); |
106 | 107 |
107 // Destroying a SchedulerWorker in production is not allowed; it is always | |
108 // leaked. In tests, it can only be destroyed after JoinForTesting() has | |
109 // returned. | |
110 ~SchedulerWorker(); | |
111 | |
112 // Wakes up this SchedulerWorker if it wasn't already awake. After this | 108 // Wakes up this SchedulerWorker if it wasn't already awake. After this |
113 // is called, this SchedulerWorker will run Tasks from Sequences | 109 // is called, this SchedulerWorker will run Tasks from Sequences |
114 // returned by the GetWork() method of its delegate until it returns nullptr. | 110 // returned by the GetWork() method of its delegate until it returns nullptr. |
115 // WakeUp() may fail if the worker is detached and it fails to allocate a new | 111 // WakeUp() may fail if the worker is detached and it fails to allocate a new |
116 // worker. If this happens, there will be no call to GetWork(). | 112 // worker. If this happens, there will be no call to GetWork(). |
117 void WakeUp(); | 113 void WakeUp(); |
118 | 114 |
119 SchedulerWorker::Delegate* delegate() { return delegate_.get(); } | 115 SchedulerWorker::Delegate* delegate() { return delegate_.get(); } |
120 | 116 |
121 // Joins this SchedulerWorker. If a Task is already running, it will be | 117 // Joins this SchedulerWorker. If a Task is already running, it will be |
122 // allowed to complete its execution. This can only be called once. | 118 // allowed to complete its execution. This can only be called once. |
123 // | 119 // |
124 // Note: A thread that detaches before JoinForTesting() is called may still be | 120 // Note: A thread that detaches before JoinForTesting() is called may still be |
125 // running after JoinForTesting() returns. However, it can't run tasks after | 121 // running after JoinForTesting() returns. However, it can't run tasks after |
126 // JoinForTesting() returns. | 122 // JoinForTesting() returns. |
127 void JoinForTesting(); | 123 void JoinForTesting(); |
128 | 124 |
129 // Returns true if the worker is alive. | 125 // Returns true if the worker is alive. |
130 bool ThreadAliveForTesting() const; | 126 bool ThreadAliveForTesting() const; |
131 | 127 |
128 // Makes a request to terminate the worker. This may be called from any | |
129 // thread. All further method calls are undefined after this calling this | |
130 // function. | |
131 void RequestThreadTermination(); | |
132 | |
132 private: | 133 private: |
134 friend class RefCountedThreadSafe<SchedulerWorker>; | |
133 class Thread; | 135 class Thread; |
136 enum class DetachNotify { | |
137 // Do not notify any component. | |
138 SILENT, | |
139 // Notify the delegate. | |
140 DELEGATE, | |
141 }; | |
134 | 142 |
135 SchedulerWorker(ThreadPriority thread_priority, | 143 SchedulerWorker(ThreadPriority thread_priority, |
136 std::unique_ptr<Delegate> delegate, | 144 std::unique_ptr<Delegate> delegate, |
137 TaskTracker* task_tracker, | 145 TaskTracker* task_tracker, |
138 SchedulerBackwardCompatibility backward_compatibility); | 146 SchedulerBackwardCompatibility backward_compatibility); |
147 ~SchedulerWorker(); | |
139 | 148 |
140 // Returns the thread instance if the detach was successful so that it can be | 149 // Returns ownership of the thread instance when appropriate so that it can be |
141 // freed upon termination of the thread. | 150 // freed upon termination of the thread. If ownership transfer is not |
142 // If the detach is not possible, returns nullptr. | 151 // possible, returns nullptr. |
143 std::unique_ptr<SchedulerWorker::Thread> Detach(); | 152 std::unique_ptr<SchedulerWorker::Thread> DetachThreadObject( |
153 DetachNotify detach_notify); | |
144 | 154 |
145 void CreateThread(); | 155 void CreateThread(); |
146 | 156 |
147 void CreateThreadAssertSynchronized(); | 157 void CreateThreadAssertSynchronized(); |
148 | 158 |
149 // Synchronizes access to |thread_|. | 159 bool ShouldExit(); |
160 | |
161 // Synchronizes access to |thread_| and |should_exit_|. | |
150 mutable SchedulerLock thread_lock_; | 162 mutable SchedulerLock thread_lock_; |
151 | 163 |
164 // AtomicFlag isn't used here as |should_exit_| may be set by any thread. | |
165 bool should_exit_ = false; | |
fdoray
2017/02/17 16:43:41
Since it is only set once [1], the fact that it ma
robliao
2017/02/17 19:24:36
Gotcha. I must have misread something somewhere as
| |
166 | |
152 // The underlying thread for this SchedulerWorker. | 167 // The underlying thread for this SchedulerWorker. |
168 // The thread object will be cleaned up by the running thread unless we join | |
169 // against the thread. Joining requires the thread object to remain alive for | |
170 // the Thread::Join() call. | |
153 std::unique_ptr<Thread> thread_; | 171 std::unique_ptr<Thread> thread_; |
154 | 172 |
155 const ThreadPriority priority_hint_; | 173 const ThreadPriority priority_hint_; |
156 | 174 |
157 const std::unique_ptr<Delegate> delegate_; | 175 const std::unique_ptr<Delegate> delegate_; |
158 TaskTracker* const task_tracker_; | 176 TaskTracker* const task_tracker_; |
159 | 177 |
160 #if defined(OS_WIN) | 178 #if defined(OS_WIN) |
161 const SchedulerBackwardCompatibility backward_compatibility_; | 179 const SchedulerBackwardCompatibility backward_compatibility_; |
162 #endif | 180 #endif |
163 | 181 |
164 // Set once JoinForTesting() has been called. | 182 // Set once JoinForTesting() has been called. |
165 AtomicFlag should_exit_for_testing_; | 183 AtomicFlag join_called_for_testing_; |
166 | 184 |
167 DISALLOW_COPY_AND_ASSIGN(SchedulerWorker); | 185 DISALLOW_COPY_AND_ASSIGN(SchedulerWorker); |
168 }; | 186 }; |
169 | 187 |
170 } // namespace internal | 188 } // namespace internal |
171 } // namespace base | 189 } // namespace base |
172 | 190 |
173 #endif // BASE_TASK_SCHEDULER_SCHEDULER_WORKER_H_ | 191 #endif // BASE_TASK_SCHEDULER_SCHEDULER_WORKER_H_ |
OLD | NEW |