| 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 #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 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 if (sleep_time.is_max()) { | 194 if (sleep_time.is_max()) { |
| 195 // Calling TimedWait with TimeDelta::Max is not recommended per | 195 // Calling TimedWait with TimeDelta::Max is not recommended per |
| 196 // http://crbug.com/465948. | 196 // http://crbug.com/465948. |
| 197 wake_up_event->Wait(); | 197 wake_up_event->Wait(); |
| 198 } else { | 198 } else { |
| 199 wake_up_event->TimedWait(sleep_time); | 199 wake_up_event->TimedWait(sleep_time); |
| 200 } | 200 } |
| 201 wake_up_event->Reset(); | 201 wake_up_event->Reset(); |
| 202 } | 202 } |
| 203 | 203 |
| 204 scoped_refptr<SchedulerWorker> SchedulerWorker::Create( | 204 SchedulerWorker::SchedulerWorker( |
| 205 ThreadPriority priority_hint, | 205 ThreadPriority priority_hint, |
| 206 std::unique_ptr<Delegate> delegate, | 206 std::unique_ptr<Delegate> delegate, |
| 207 TaskTracker* task_tracker, | 207 TaskTracker* task_tracker, |
| 208 InitialState initial_state, | 208 SchedulerBackwardCompatibility backward_compatibility, |
| 209 SchedulerBackwardCompatibility backward_compatibility) { | 209 InitialState initial_state) |
| 210 scoped_refptr<SchedulerWorker> worker( | 210 : priority_hint_(priority_hint), |
| 211 new SchedulerWorker(priority_hint, std::move(delegate), task_tracker, | 211 delegate_(std::move(delegate)), |
| 212 backward_compatibility)); | 212 task_tracker_(task_tracker), |
| 213 // Creation happens before any other thread can reference this one, so no | 213 #if defined(OS_WIN) |
| 214 // synchronization is necessary. | 214 backward_compatibility_(backward_compatibility), |
| 215 if (initial_state == SchedulerWorker::InitialState::ALIVE) { | 215 #endif |
| 216 worker->CreateThread(); | 216 initial_state_(initial_state) { |
| 217 if (!worker->thread_) { | 217 DCHECK(delegate_); |
| 218 return nullptr; | 218 DCHECK(task_tracker_); |
| 219 } | 219 } |
| 220 |
| 221 bool SchedulerWorker::Start() { |
| 222 AutoSchedulerLock auto_lock(thread_lock_); |
| 223 DCHECK(!started_); |
| 224 DCHECK(!thread_); |
| 225 |
| 226 if (should_exit_.IsSet()) |
| 227 return true; |
| 228 |
| 229 started_ = true; |
| 230 |
| 231 if (initial_state_ == InitialState::ALIVE) { |
| 232 CreateThread(); |
| 233 return !!thread_; |
| 220 } | 234 } |
| 221 | 235 |
| 222 return worker; | 236 return true; |
| 223 } | 237 } |
| 224 | 238 |
| 225 void SchedulerWorker::WakeUp() { | 239 void SchedulerWorker::WakeUp() { |
| 226 AutoSchedulerLock auto_lock(thread_lock_); | 240 AutoSchedulerLock auto_lock(thread_lock_); |
| 227 | 241 |
| 228 DCHECK(!join_called_for_testing_.IsSet()); | 242 DCHECK(!join_called_for_testing_.IsSet()); |
| 229 | 243 |
| 230 if (!thread_) | 244 if (!thread_) |
| 231 CreateThreadAssertSynchronized(); | 245 CreateThread(); |
| 232 | 246 |
| 233 if (thread_) | 247 if (thread_) |
| 234 thread_->WakeUp(); | 248 thread_->WakeUp(); |
| 235 } | 249 } |
| 236 | 250 |
| 237 void SchedulerWorker::JoinForTesting() { | 251 void SchedulerWorker::JoinForTesting() { |
| 252 DCHECK(started_); |
| 238 DCHECK(!join_called_for_testing_.IsSet()); | 253 DCHECK(!join_called_for_testing_.IsSet()); |
| 239 join_called_for_testing_.Set(); | 254 join_called_for_testing_.Set(); |
| 240 | 255 |
| 241 std::unique_ptr<Thread> thread; | 256 std::unique_ptr<Thread> thread; |
| 242 | 257 |
| 243 { | 258 { |
| 244 AutoSchedulerLock auto_lock(thread_lock_); | 259 AutoSchedulerLock auto_lock(thread_lock_); |
| 245 | 260 |
| 246 if (thread_) { | 261 if (thread_) { |
| 247 // Make sure the thread is awake. It will see that | 262 // Make sure the thread is awake. It will see that |
| (...skipping 11 matching lines...) Expand all Loading... |
| 259 AutoSchedulerLock auto_lock(thread_lock_); | 274 AutoSchedulerLock auto_lock(thread_lock_); |
| 260 return !!thread_; | 275 return !!thread_; |
| 261 } | 276 } |
| 262 | 277 |
| 263 void SchedulerWorker::Cleanup() { | 278 void SchedulerWorker::Cleanup() { |
| 264 // |should_exit_| is synchronized with |thread_| for writes here so that we | 279 // |should_exit_| is synchronized with |thread_| for writes here so that we |
| 265 // can maintain access to |thread_| for wakeup. Otherwise, the thread may take | 280 // can maintain access to |thread_| for wakeup. Otherwise, the thread may take |
| 266 // away |thread_| for destruction. | 281 // away |thread_| for destruction. |
| 267 AutoSchedulerLock auto_lock(thread_lock_); | 282 AutoSchedulerLock auto_lock(thread_lock_); |
| 268 DCHECK(!should_exit_.IsSet()); | 283 DCHECK(!should_exit_.IsSet()); |
| 269 if (thread_) { | 284 should_exit_.Set(); |
| 270 should_exit_.Set(); | 285 if (thread_) |
| 271 thread_->WakeUp(); | 286 thread_->WakeUp(); |
| 272 } | |
| 273 } | |
| 274 | |
| 275 SchedulerWorker::SchedulerWorker( | |
| 276 ThreadPriority priority_hint, | |
| 277 std::unique_ptr<Delegate> delegate, | |
| 278 TaskTracker* task_tracker, | |
| 279 SchedulerBackwardCompatibility backward_compatibility) | |
| 280 : priority_hint_(priority_hint), | |
| 281 delegate_(std::move(delegate)), | |
| 282 task_tracker_(task_tracker) | |
| 283 #if defined(OS_WIN) | |
| 284 , | |
| 285 backward_compatibility_(backward_compatibility) | |
| 286 #endif | |
| 287 { | |
| 288 DCHECK(delegate_); | |
| 289 DCHECK(task_tracker_); | |
| 290 } | 287 } |
| 291 | 288 |
| 292 SchedulerWorker::~SchedulerWorker() { | 289 SchedulerWorker::~SchedulerWorker() { |
| 293 // It is unexpected for |thread_| to be alive and for SchedulerWorker to | 290 // It is unexpected for |thread_| to be alive and for SchedulerWorker to |
| 294 // destroy since SchedulerWorker owns the delegate needed by |thread_|. | 291 // destroy since SchedulerWorker owns the delegate needed by |thread_|. |
| 295 // For testing, this generally means JoinForTesting was not called. | 292 // For testing, this generally means JoinForTesting was not called. |
| 296 DCHECK(!thread_); | 293 DCHECK(!thread_); |
| 297 } | 294 } |
| 298 | 295 |
| 299 std::unique_ptr<SchedulerWorker::Thread> SchedulerWorker::DetachThreadObject( | 296 std::unique_ptr<SchedulerWorker::Thread> SchedulerWorker::DetachThreadObject( |
| (...skipping 15 matching lines...) Expand all Loading... |
| 315 if (detach_notify == DetachNotify::DELEGATE) { | 312 if (detach_notify == DetachNotify::DELEGATE) { |
| 316 // Call OnDetach() within the scope of |thread_lock_| to prevent the | 313 // Call OnDetach() within the scope of |thread_lock_| to prevent the |
| 317 // delegate from being used concurrently from an old and a new thread. | 314 // delegate from being used concurrently from an old and a new thread. |
| 318 delegate_->OnDetach(); | 315 delegate_->OnDetach(); |
| 319 } | 316 } |
| 320 | 317 |
| 321 return std::move(thread_); | 318 return std::move(thread_); |
| 322 } | 319 } |
| 323 | 320 |
| 324 void SchedulerWorker::CreateThread() { | 321 void SchedulerWorker::CreateThread() { |
| 325 thread_ = Thread::Create(make_scoped_refptr(this)); | |
| 326 } | |
| 327 | |
| 328 void SchedulerWorker::CreateThreadAssertSynchronized() { | |
| 329 thread_lock_.AssertAcquired(); | 322 thread_lock_.AssertAcquired(); |
| 330 CreateThread(); | 323 if (started_) |
| 324 thread_ = Thread::Create(make_scoped_refptr(this)); |
| 331 } | 325 } |
| 332 | 326 |
| 333 bool SchedulerWorker::ShouldExit() { | 327 bool SchedulerWorker::ShouldExit() { |
| 334 // The ordering of the checks is important below. This SchedulerWorker may be | 328 // The ordering of the checks is important below. This SchedulerWorker may be |
| 335 // released and outlive |task_tracker_| in unit tests. However, when the | 329 // released and outlive |task_tracker_| in unit tests. However, when the |
| 336 // SchedulerWorker is released, |should_exit_| will be set, so check that | 330 // SchedulerWorker is released, |should_exit_| will be set, so check that |
| 337 // first. | 331 // first. |
| 338 return should_exit_.IsSet() || join_called_for_testing_.IsSet() || | 332 return should_exit_.IsSet() || join_called_for_testing_.IsSet() || |
| 339 task_tracker_->IsShutdownComplete(); | 333 task_tracker_->IsShutdownComplete(); |
| 340 } | 334 } |
| 341 | 335 |
| 342 } // namespace internal | 336 } // namespace internal |
| 343 } // namespace base | 337 } // namespace base |
| OLD | NEW |