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

Side by Side Diff: base/task_scheduler/scheduler_worker.cc

Issue 2686593003: DESIGN DISCUSSION ONLY Task Scheduler Single Thread Task Runner Manager for Dedicated Threads per S… (Closed)
Patch Set: Wait for Detached Thread to Complete Created 3 years, 10 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 #include "base/task_scheduler/scheduler_worker.h" 5 #include "base/task_scheduler/scheduler_worker.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <utility> 9 #include <utility>
10 10
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 // added to it. Otherwise, it will be destroyed at the end of this scope. 91 // added to it. Otherwise, it will be destroyed at the end of this scope.
92 if (!sequence_became_empty) 92 if (!sequence_became_empty)
93 outer_->delegate_->ReEnqueueSequence(std::move(sequence)); 93 outer_->delegate_->ReEnqueueSequence(std::move(sequence));
94 94
95 // Calling WakeUp() guarantees that this SchedulerWorker will run 95 // Calling WakeUp() guarantees that this SchedulerWorker will run
96 // Tasks from Sequences returned by the GetWork() method of |delegate_| 96 // Tasks from Sequences returned by the GetWork() method of |delegate_|
97 // until it returns nullptr. Resetting |wake_up_event_| here doesn't break 97 // until it returns nullptr. Resetting |wake_up_event_| here doesn't break
98 // this invariant and avoids a useless loop iteration before going to 98 // this invariant and avoids a useless loop iteration before going to
99 // sleep if WakeUp() is called while this SchedulerWorker is awake. 99 // sleep if WakeUp() is called while this SchedulerWorker is awake.
100 wake_up_event_.Reset(); 100 wake_up_event_.Reset();
101 } 101 }
fdoray 2017/02/08 17:59:01 There is a leak if someone does this: TEST(...) {
robliao 2017/02/11 02:13:34 Thanks for pointing this out. This is covered by a
102 102
103 // If a wake up is pending and we successfully detached, somehow |outer_| 103 // If a wake up is pending and we successfully detached, somehow |outer_|
104 // was able to signal us which means it probably thinks we're still alive. 104 // was able to signal us which means it probably thinks we're still alive.
105 // This is bad as it will cause the WakeUp to no-op and |outer_| will be 105 // This is bad as it will cause the WakeUp to no-op and |outer_| will be
106 // stuck forever. 106 // stuck forever.
107 DCHECK(!detached_thread || !IsWakeUpPending()) << 107 DCHECK(!detached_thread || !IsWakeUpPending()) <<
108 "This thread was detached and woken up at the same time."; 108 "This thread was detached and woken up at the same time.";
109 } 109 }
110 110
111 void TakeOwnershipOfSchedulerWorker(std::unique_ptr<SchedulerWorker> worker) {
112 // If this check fails, we'll crash on a random thread instead.
113 CHECK(outer_ == worker.get());
fdoray 2017/02/08 17:59:01 DCHECK_EQ
robliao 2017/02/10 00:04:04 This CHECK is intentional. I'd prefer to crash rig
114 owning_worker_ = std::move(worker);
fdoray 2017/02/08 17:59:01 WakeUp(); Otherwise, the thread may sleep forever
robliao 2017/02/11 02:13:34 Done.
115 }
116
111 void Join() { PlatformThread::Join(thread_handle_); } 117 void Join() { PlatformThread::Join(thread_handle_); }
112 118
113 void WakeUp() { wake_up_event_.Signal(); } 119 void WakeUp() { wake_up_event_.Signal(); }
114 120
115 bool IsWakeUpPending() { return wake_up_event_.IsSignaled(); } 121 bool IsWakeUpPending() { return wake_up_event_.IsSignaled(); }
116 122
117 private: 123 private:
118 Thread(SchedulerWorker* outer) 124 Thread(SchedulerWorker* outer)
119 : outer_(outer), 125 : outer_(outer),
120 wake_up_event_(WaitableEvent::ResetPolicy::MANUAL, 126 wake_up_event_(WaitableEvent::ResetPolicy::MANUAL,
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 183
178 SchedulerWorker* outer_; 184 SchedulerWorker* outer_;
179 185
180 // Event signaled to wake up this thread. 186 // Event signaled to wake up this thread.
181 WaitableEvent wake_up_event_; 187 WaitableEvent wake_up_event_;
182 188
183 // Current priority of this thread. May be different from 189 // Current priority of this thread. May be different from
184 // |outer_->priority_hint_|. 190 // |outer_->priority_hint_|.
185 ThreadPriority current_thread_priority_; 191 ThreadPriority current_thread_priority_;
186 192
193 // Holds the owning worker for destruction at the end of detachment.
194 std::unique_ptr<SchedulerWorker> owning_worker_;
195
187 DISALLOW_COPY_AND_ASSIGN(Thread); 196 DISALLOW_COPY_AND_ASSIGN(Thread);
188 }; 197 };
189 198
190 std::unique_ptr<SchedulerWorker> SchedulerWorker::Create( 199 std::unique_ptr<SchedulerWorker> SchedulerWorker::Create(
191 ThreadPriority priority_hint, 200 ThreadPriority priority_hint,
192 std::unique_ptr<Delegate> delegate, 201 std::unique_ptr<Delegate> delegate,
193 TaskTracker* task_tracker, 202 TaskTracker* task_tracker,
194 InitialState initial_state, 203 InitialState initial_state,
195 SchedulerBackwardCompatibility backward_compatibility) { 204 SchedulerBackwardCompatibility backward_compatibility) {
196 auto worker = 205 auto worker =
(...skipping 11 matching lines...) Expand all
208 return worker; 217 return worker;
209 } 218 }
210 219
211 SchedulerWorker::~SchedulerWorker() { 220 SchedulerWorker::~SchedulerWorker() {
212 // It is unexpected for |thread_| to be alive and for SchedulerWorker to 221 // It is unexpected for |thread_| to be alive and for SchedulerWorker to
213 // destroy since SchedulerWorker owns the delegate needed by |thread_|. 222 // destroy since SchedulerWorker owns the delegate needed by |thread_|.
214 // For testing, this generally means JoinForTesting was not called. 223 // For testing, this generally means JoinForTesting was not called.
215 DCHECK(!thread_); 224 DCHECK(!thread_);
216 } 225 }
217 226
227 // static
228 void SchedulerWorker::DestroyAfterDetachment(
229 std::unique_ptr<SchedulerWorker> worker) {
230 DCHECK(worker);
231 AutoSchedulerLock auto_lock(worker->thread_lock_);
232 if (worker->thread_) {
233 SchedulerWorker* raw_worker_pointer = worker.get();
234 raw_worker_pointer->thread_->TakeOwnershipOfSchedulerWorker(
235 std::move(worker));
236 }
237 }
238
218 void SchedulerWorker::WakeUp() { 239 void SchedulerWorker::WakeUp() {
219 AutoSchedulerLock auto_lock(thread_lock_); 240 AutoSchedulerLock auto_lock(thread_lock_);
220 241
221 DCHECK(!should_exit_for_testing_.IsSet()); 242 DCHECK(!should_exit_for_testing_.IsSet());
222 243
223 if (!thread_) 244 if (!thread_)
224 CreateThreadAssertSynchronized(); 245 CreateThreadAssertSynchronized();
225 246
226 if (thread_) 247 if (thread_)
227 thread_->WakeUp(); 248 thread_->WakeUp();
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 thread_ = Thread::Create(this); 317 thread_ = Thread::Create(this);
297 } 318 }
298 319
299 void SchedulerWorker::CreateThreadAssertSynchronized() { 320 void SchedulerWorker::CreateThreadAssertSynchronized() {
300 thread_lock_.AssertAcquired(); 321 thread_lock_.AssertAcquired();
301 CreateThread(); 322 CreateThread();
302 } 323 }
303 324
304 } // namespace internal 325 } // namespace internal
305 } // namespace base 326 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698