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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 | 89 |
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. Either JoinForTesting() or Cleanup() must be called before |
99 static std::unique_ptr<SchedulerWorker> Create( | 100 // releasing the last external reference. |
| 101 static scoped_refptr<SchedulerWorker> Create( |
100 ThreadPriority priority_hint, | 102 ThreadPriority priority_hint, |
101 std::unique_ptr<Delegate> delegate, | 103 std::unique_ptr<Delegate> delegate, |
102 TaskTracker* task_tracker, | 104 TaskTracker* task_tracker, |
103 InitialState initial_state, | 105 InitialState initial_state, |
104 SchedulerBackwardCompatibility backward_compatibility = | 106 SchedulerBackwardCompatibility backward_compatibility = |
105 SchedulerBackwardCompatibility::DISABLED); | 107 SchedulerBackwardCompatibility::DISABLED); |
106 | 108 |
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 | 109 // Wakes up this SchedulerWorker if it wasn't already awake. After this |
113 // is called, this SchedulerWorker will run Tasks from Sequences | 110 // is called, this SchedulerWorker will run Tasks from Sequences |
114 // returned by the GetWork() method of its delegate until it returns nullptr. | 111 // 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 | 112 // 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(). | 113 // worker. If this happens, there will be no call to GetWork(). |
117 void WakeUp(); | 114 void WakeUp(); |
118 | 115 |
119 SchedulerWorker::Delegate* delegate() { return delegate_.get(); } | 116 SchedulerWorker::Delegate* delegate() { return delegate_.get(); } |
120 | 117 |
121 // Joins this SchedulerWorker. If a Task is already running, it will be | 118 // Joins this SchedulerWorker. If a Task is already running, it will be |
122 // allowed to complete its execution. This can only be called once. | 119 // allowed to complete its execution. This can only be called once. |
123 // | 120 // |
124 // Note: A thread that detaches before JoinForTesting() is called may still be | 121 // Note: A thread that detaches before JoinForTesting() is called may still be |
125 // running after JoinForTesting() returns. However, it can't run tasks after | 122 // running after JoinForTesting() returns. However, it can't run tasks after |
126 // JoinForTesting() returns. | 123 // JoinForTesting() returns. |
127 void JoinForTesting(); | 124 void JoinForTesting(); |
128 | 125 |
129 // Returns true if the worker is alive. | 126 // Returns true if the worker is alive. |
130 bool ThreadAliveForTesting() const; | 127 bool ThreadAliveForTesting() const; |
131 | 128 |
| 129 // Makes a request to cleanup the worker. This may be called from any thread. |
| 130 // The caller is expected to release its reference to this object after |
| 131 // calling Cleanup(). Further method calls after Cleanup() returns are |
| 132 // undefined. |
| 133 // |
| 134 // Expected Usage: |
| 135 // scoped_refptr<SchedulerWorker> worker_ = /* Existing Worker */ |
| 136 // worker_->Cleanup(); |
| 137 // worker_ = nullptr; |
| 138 void Cleanup(); |
| 139 |
132 private: | 140 private: |
| 141 friend class RefCountedThreadSafe<SchedulerWorker>; |
133 class Thread; | 142 class Thread; |
| 143 enum class DetachNotify { |
| 144 // Do not notify any component. |
| 145 SILENT, |
| 146 // Notify the delegate. |
| 147 DELEGATE, |
| 148 }; |
134 | 149 |
135 SchedulerWorker(ThreadPriority thread_priority, | 150 SchedulerWorker(ThreadPriority thread_priority, |
136 std::unique_ptr<Delegate> delegate, | 151 std::unique_ptr<Delegate> delegate, |
137 TaskTracker* task_tracker, | 152 TaskTracker* task_tracker, |
138 SchedulerBackwardCompatibility backward_compatibility); | 153 SchedulerBackwardCompatibility backward_compatibility); |
| 154 ~SchedulerWorker(); |
139 | 155 |
140 // Returns the thread instance if the detach was successful so that it can be | 156 // Returns ownership of the thread instance when appropriate so that it can be |
141 // freed upon termination of the thread. | 157 // freed upon termination of the thread. If ownership transfer is not |
142 // If the detach is not possible, returns nullptr. | 158 // possible, returns nullptr. |
143 std::unique_ptr<SchedulerWorker::Thread> Detach(); | 159 std::unique_ptr<SchedulerWorker::Thread> DetachThreadObject( |
| 160 DetachNotify detach_notify); |
144 | 161 |
145 void CreateThread(); | 162 void CreateThread(); |
146 | 163 |
147 void CreateThreadAssertSynchronized(); | 164 void CreateThreadAssertSynchronized(); |
148 | 165 |
149 // Synchronizes access to |thread_|. | 166 bool ShouldExit(); |
| 167 |
| 168 // Synchronizes access to |thread_| (read+write) as well as |should_exit_| |
| 169 // (write-only). See Cleanup() for details. |
150 mutable SchedulerLock thread_lock_; | 170 mutable SchedulerLock thread_lock_; |
151 | 171 |
| 172 AtomicFlag should_exit_; |
| 173 |
152 // The underlying thread for this SchedulerWorker. | 174 // The underlying thread for this SchedulerWorker. |
| 175 // The thread object will be cleaned up by the running thread unless we join |
| 176 // against the thread. Joining requires the thread object to remain alive for |
| 177 // the Thread::Join() call. |
153 std::unique_ptr<Thread> thread_; | 178 std::unique_ptr<Thread> thread_; |
154 | 179 |
155 const ThreadPriority priority_hint_; | 180 const ThreadPriority priority_hint_; |
156 | 181 |
157 const std::unique_ptr<Delegate> delegate_; | 182 const std::unique_ptr<Delegate> delegate_; |
158 TaskTracker* const task_tracker_; | 183 TaskTracker* const task_tracker_; |
159 | 184 |
160 #if defined(OS_WIN) | 185 #if defined(OS_WIN) |
161 const SchedulerBackwardCompatibility backward_compatibility_; | 186 const SchedulerBackwardCompatibility backward_compatibility_; |
162 #endif | 187 #endif |
163 | 188 |
164 // Set once JoinForTesting() has been called. | 189 // Set once JoinForTesting() has been called. |
165 AtomicFlag should_exit_for_testing_; | 190 AtomicFlag join_called_for_testing_; |
166 | 191 |
167 DISALLOW_COPY_AND_ASSIGN(SchedulerWorker); | 192 DISALLOW_COPY_AND_ASSIGN(SchedulerWorker); |
168 }; | 193 }; |
169 | 194 |
170 } // namespace internal | 195 } // namespace internal |
171 } // namespace base | 196 } // namespace base |
172 | 197 |
173 #endif // BASE_TASK_SCHEDULER_SCHEDULER_WORKER_H_ | 198 #endif // BASE_TASK_SCHEDULER_SCHEDULER_WORKER_H_ |
OLD | NEW |