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

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

Issue 2902753003: Implement Shared SingleThreadTaskRunners in the Task Scheduler (Closed)
Patch Set: Created 3 years, 7 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 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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_single_thread_task_runner_manager.h" 5 #include "base/task_scheduler/scheduler_single_thread_task_runner_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <memory> 8 #include <memory>
9 #include <string> 9 #include <string>
10 #include <utility> 10 #include <utility>
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 OnceClosure closure, 276 OnceClosure closure,
277 TimeDelta delay) override { 277 TimeDelta delay) override {
278 // Tasks are never nested within the task scheduler. 278 // Tasks are never nested within the task scheduler.
279 return PostDelayedTask(from_here, std::move(closure), delay); 279 return PostDelayedTask(from_here, std::move(closure), delay);
280 } 280 }
281 281
282 bool RunsTasksInCurrentSequence() const override { 282 bool RunsTasksInCurrentSequence() const override {
283 return GetDelegate()->RunsTasksInCurrentSequence(); 283 return GetDelegate()->RunsTasksInCurrentSequence();
284 } 284 }
285 285
286 // SchedulerSingleThreadTaskRunner:
fdoray 2017/05/24 13:25:45 Update comment. This isn't an override.
robliao 2017/05/24 18:28:32 The headers are not strictly used for overrides, b
287 void Start() { worker_->Start(); }
288
286 private: 289 private:
287 ~SchedulerSingleThreadTaskRunner() override { 290 ~SchedulerSingleThreadTaskRunner() override {
288 // Note: This will crash if SchedulerSingleThreadTaskRunnerManager is 291 // Note: This will crash if SchedulerSingleThreadTaskRunnerManager is
289 // incorrectly destroyed first in tests (in production the TaskScheduler and 292 // incorrectly destroyed first in tests (in production the TaskScheduler and
290 // all of its state are intentionally leaked after 293 // all of its state are intentionally leaked after
291 // TaskScheduler::Shutdown(). See ~SchedulerSingleThreadTaskRunnerManager() 294 // TaskScheduler::Shutdown(). See ~SchedulerSingleThreadTaskRunnerManager()
292 // for more details. 295 // for more details.
293 outer_->UnregisterSchedulerWorker(worker_); 296 outer_->UnregisterSchedulerWorker(worker_);
294 } 297 }
295 298
(...skipping 21 matching lines...) Expand all
317 320
318 DISALLOW_COPY_AND_ASSIGN(SchedulerSingleThreadTaskRunner); 321 DISALLOW_COPY_AND_ASSIGN(SchedulerSingleThreadTaskRunner);
319 }; 322 };
320 323
321 SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunnerManager( 324 SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunnerManager(
322 TaskTracker* task_tracker, 325 TaskTracker* task_tracker,
323 DelayedTaskManager* delayed_task_manager) 326 DelayedTaskManager* delayed_task_manager)
324 : task_tracker_(task_tracker), delayed_task_manager_(delayed_task_manager) { 327 : task_tracker_(task_tracker), delayed_task_manager_(delayed_task_manager) {
325 DCHECK(task_tracker_); 328 DCHECK(task_tracker_);
326 DCHECK(delayed_task_manager_); 329 DCHECK(delayed_task_manager_);
330 static_assert(
331 arraysize(shared_task_runners_) == ENVIRONMENT_COUNT,
332 "The size of |shared_task_runners_| must match ENVIRONMENT_COUNT");
333 #if defined(OS_WIN)
334 static_assert(
335 arraysize(shared_com_task_runners_) == arraysize(shared_task_runners_),
336 "The size of |shared_com_task_runners_| must match "
337 "|shared_task_runners_|");
338 #endif // defined(OS_WIN)
327 } 339 }
328 340
329 SchedulerSingleThreadTaskRunnerManager:: 341 SchedulerSingleThreadTaskRunnerManager::
330 ~SchedulerSingleThreadTaskRunnerManager() { 342 ~SchedulerSingleThreadTaskRunnerManager() {
331 #if DCHECK_IS_ON() 343 #if DCHECK_IS_ON()
332 size_t workers_unregistered_during_join = 344 size_t workers_unregistered_during_join =
333 subtle::NoBarrier_Load(&workers_unregistered_during_join_); 345 subtle::NoBarrier_Load(&workers_unregistered_during_join_);
334 // Log an ERROR instead of DCHECK'ing as it's often useful to have both the 346 // Log an ERROR instead of DCHECK'ing as it's often useful to have both the
335 // stack trace of this call and the crash stack trace of the upcoming 347 // stack trace of this call and the crash stack trace of the upcoming
336 // out-of-order ~SchedulerSingleThreadTaskRunner() call to know what to flip. 348 // out-of-order ~SchedulerSingleThreadTaskRunner() call to know what to flip.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 // workers are started as they are created. 380 // workers are started as they are created.
369 for (scoped_refptr<SchedulerWorker> worker : workers_to_start) { 381 for (scoped_refptr<SchedulerWorker> worker : workers_to_start) {
370 worker->Start(); 382 worker->Start();
371 worker->WakeUp(); 383 worker->WakeUp();
372 } 384 }
373 } 385 }
374 386
375 scoped_refptr<SingleThreadTaskRunner> 387 scoped_refptr<SingleThreadTaskRunner>
376 SchedulerSingleThreadTaskRunnerManager::CreateSingleThreadTaskRunnerWithTraits( 388 SchedulerSingleThreadTaskRunnerManager::CreateSingleThreadTaskRunnerWithTraits(
377 const std::string& name, 389 const std::string& name,
378 ThreadPriority priority_hint, 390 ThreadPriority priority_hint,
fdoray 2017/05/24 13:25:45 Now that this file includes "base/task_scheduler/e
robliao 2017/05/24 18:28:32 Done.
379 const TaskTraits& traits) { 391 const TaskTraits& traits,
380 return CreateSingleThreadTaskRunnerWithDelegate<SchedulerWorkerDelegate>( 392 SingleThreadTaskRunnerThreadMode thread_mode) {
381 name, priority_hint, traits); 393 return CreateTaskRunnerWithTraitsImpl<SchedulerWorkerDelegate>(
394 name, priority_hint, traits, thread_mode);
382 } 395 }
383 396
384 #if defined(OS_WIN) 397 #if defined(OS_WIN)
385 scoped_refptr<SingleThreadTaskRunner> 398 scoped_refptr<SingleThreadTaskRunner>
386 SchedulerSingleThreadTaskRunnerManager::CreateCOMSTATaskRunnerWithTraits( 399 SchedulerSingleThreadTaskRunnerManager::CreateCOMSTATaskRunnerWithTraits(
387 const std::string& name, 400 const std::string& name,
388 ThreadPriority priority_hint, 401 ThreadPriority priority_hint,
389 const TaskTraits& traits) { 402 const TaskTraits& traits,
390 return CreateSingleThreadTaskRunnerWithDelegate<SchedulerWorkerCOMDelegate>( 403 SingleThreadTaskRunnerThreadMode thread_mode) {
391 name, priority_hint, traits); 404 return CreateTaskRunnerWithTraitsImpl<SchedulerWorkerCOMDelegate>(
405 name, priority_hint, traits, thread_mode);
392 } 406 }
393 #endif // defined(OS_WIN) 407 #endif // defined(OS_WIN)
394 408
409 template <typename DelegateType>
410 scoped_refptr<
411 SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunner>
412 SchedulerSingleThreadTaskRunnerManager::CreateTaskRunnerWithTraitsImpl(
413 const std::string& name,
414 ThreadPriority priority_hint,
415 const TaskTraits& traits,
416 SingleThreadTaskRunnerThreadMode thread_mode) {
fdoray 2017/05/24 13:25:45 I would assert that WithBaseSyncPrimitives() is no
robliao 2017/05/24 18:28:32 Sounds reasonable to me. Done.
417 // To simply the code, |dedicated_task_runner| is a local only variable that
fdoray 2017/05/24 13:25:45 To *simplify*
robliao 2017/05/24 18:28:32 Done.
418 // allows the code to treat both the DEDICATED and SHARED cases similarly. In
419 // DEDICATED, the scoped_refptr is backed by a local variable and in SHARED,
420 // the scoped_refptr is backed by a member variable.
421 scoped_refptr<SchedulerSingleThreadTaskRunner> dedicated_task_runner;
422 scoped_refptr<SchedulerSingleThreadTaskRunner>& task_runner =
423 thread_mode == SingleThreadTaskRunnerThreadMode::DEDICATED
424 ? dedicated_task_runner
425 : GetSharedTaskRunnerForTraits<DelegateType>(traits);
426 bool new_task_runner = false;
427 bool started;
428 {
429 AutoSchedulerLock auto_lock(lock_);
430 if (!task_runner) {
431 std::string processed_name =
432 thread_mode == SingleThreadTaskRunnerThreadMode::DEDICATED
433 ? name
434 : "Shared" + name;
435 task_runner = CreateSingleThreadTaskRunnerWithDelegate<DelegateType>(
436 processed_name, priority_hint, traits);
fdoray 2017/05/24 13:25:45 Unfortunately, if someone creates a SingleThreadTa
robliao 2017/05/24 18:28:32 Nice catch. Fixed to reuse SchedulerWorkers.
437 new_task_runner = true;
438 }
439 started = started_;
440 }
441
442 if (new_task_runner && started)
443 task_runner->Start();
fdoray 2017/05/24 13:25:45 What do you think of rewriting this method as: te
robliao 2017/05/24 18:28:32 sgtm. Done.
444
445 return task_runner;
446 }
447
395 void SchedulerSingleThreadTaskRunnerManager::JoinForTesting() { 448 void SchedulerSingleThreadTaskRunnerManager::JoinForTesting() {
449 ReleaseSharedTaskRunners();
fdoray 2017/05/24 13:25:45 Why is this needed? SchedulerWorker::JoinForTestin
robliao 2017/05/24 18:28:32 This is now ReleaseSharedSchedulerWorkers() and is
450
396 decltype(workers_) local_workers; 451 decltype(workers_) local_workers;
397 { 452 {
398 AutoSchedulerLock auto_lock(lock_); 453 AutoSchedulerLock auto_lock(lock_);
399 local_workers = std::move(workers_); 454 local_workers = std::move(workers_);
400 } 455 }
401 456
402 for (const auto& worker : local_workers) 457 for (const auto& worker : local_workers)
403 worker->JoinForTesting(); 458 worker->JoinForTesting();
404 459
405 { 460 {
406 AutoSchedulerLock auto_lock(lock_); 461 AutoSchedulerLock auto_lock(lock_);
407 DCHECK(workers_.empty()) 462 DCHECK(workers_.empty())
408 << "New worker(s) unexpectedly registered during join."; 463 << "New worker(s) unexpectedly registered during join.";
409 workers_ = std::move(local_workers); 464 workers_ = std::move(local_workers);
410 } 465 }
411 } 466 }
412 467
413 template <typename DelegateType> 468 template <typename DelegateType>
414 scoped_refptr<SingleThreadTaskRunner> SchedulerSingleThreadTaskRunnerManager:: 469 scoped_refptr<
470 SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunner>
471 SchedulerSingleThreadTaskRunnerManager::
415 CreateSingleThreadTaskRunnerWithDelegate(const std::string& name, 472 CreateSingleThreadTaskRunnerWithDelegate(const std::string& name,
416 ThreadPriority priority_hint, 473 ThreadPriority priority_hint,
417 const TaskTraits& traits) { 474 const TaskTraits& traits) {
418 return new SchedulerSingleThreadTaskRunner( 475 return new SchedulerSingleThreadTaskRunner(
419 this, traits, 476 this, traits,
420 CreateAndRegisterSchedulerWorker<DelegateType>(name, priority_hint)); 477 CreateAndRegisterSchedulerWorker<DelegateType>(name, priority_hint));
421 } 478 }
422 479
423 template <> 480 template <>
424 std::unique_ptr<SchedulerWorkerDelegate> 481 std::unique_ptr<SchedulerWorkerDelegate>
(...skipping 12 matching lines...) Expand all
437 StringPrintf("TaskSchedulerSingleThreadCOMSTA%s%d", name.c_str(), id), 494 StringPrintf("TaskSchedulerSingleThreadCOMSTA%s%d", name.c_str(), id),
438 task_tracker_); 495 task_tracker_);
439 } 496 }
440 #endif // defined(OS_WIN) 497 #endif // defined(OS_WIN)
441 498
442 template <typename DelegateType> 499 template <typename DelegateType>
443 SchedulerWorker* 500 SchedulerWorker*
444 SchedulerSingleThreadTaskRunnerManager::CreateAndRegisterSchedulerWorker( 501 SchedulerSingleThreadTaskRunnerManager::CreateAndRegisterSchedulerWorker(
445 const std::string& name, 502 const std::string& name,
446 ThreadPriority priority_hint) { 503 ThreadPriority priority_hint) {
447 SchedulerWorker* worker; 504 lock_.AssertAcquired();
448 bool start_worker; 505 int id = next_worker_id_++;
506 workers_.emplace_back(make_scoped_refptr(new SchedulerWorker(
507 priority_hint, CreateSchedulerWorkerDelegate<DelegateType>(name, id),
508 task_tracker_)));
509 return workers_.back().get();
510 }
449 511
450 { 512 template <>
451 AutoSchedulerLock auto_lock(lock_); 513 scoped_refptr<
452 int id = next_worker_id_++; 514 SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunner>&
453 workers_.emplace_back(make_scoped_refptr(new SchedulerWorker( 515 SchedulerSingleThreadTaskRunnerManager::GetSharedTaskRunnerForTraits<
454 priority_hint, CreateSchedulerWorkerDelegate<DelegateType>(name, id), 516 SchedulerWorkerDelegate>(const TaskTraits& traits) {
455 task_tracker_))); 517 return shared_task_runners_[GetEnvironmentIndexForTraits(traits)];
456 worker = workers_.back().get(); 518 }
457 start_worker = started_;
458 }
459 519
460 if (start_worker) 520 #if defined(OS_WIN)
461 worker->Start(); 521 template <>
462 522 scoped_refptr<
463 return worker; 523 SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunner>&
524 SchedulerSingleThreadTaskRunnerManager::GetSharedTaskRunnerForTraits<
525 SchedulerWorkerCOMDelegate>(const TaskTraits& traits) {
526 return shared_com_task_runners_[GetEnvironmentIndexForTraits(traits)];
464 } 527 }
528 #endif // defined(OS_WIN)
465 529
466 void SchedulerSingleThreadTaskRunnerManager::UnregisterSchedulerWorker( 530 void SchedulerSingleThreadTaskRunnerManager::UnregisterSchedulerWorker(
467 SchedulerWorker* worker) { 531 SchedulerWorker* worker) {
468 // Cleanup uses a SchedulerLock, so call Cleanup() after releasing 532 // Cleanup uses a SchedulerLock, so call Cleanup() after releasing
469 // |lock_|. 533 // |lock_|.
470 scoped_refptr<SchedulerWorker> worker_to_destroy; 534 scoped_refptr<SchedulerWorker> worker_to_destroy;
471 { 535 {
472 AutoSchedulerLock auto_lock(lock_); 536 AutoSchedulerLock auto_lock(lock_);
473 537
474 // We might be joining, so record that a worker was unregistered for 538 // We might be joining, so record that a worker was unregistered for
(...skipping 10 matching lines...) Expand all
485 [worker](const scoped_refptr<SchedulerWorker>& candidate) { 549 [worker](const scoped_refptr<SchedulerWorker>& candidate) {
486 return candidate.get() == worker; 550 return candidate.get() == worker;
487 }); 551 });
488 DCHECK(worker_iter != workers_.end()); 552 DCHECK(worker_iter != workers_.end());
489 worker_to_destroy = std::move(*worker_iter); 553 worker_to_destroy = std::move(*worker_iter);
490 workers_.erase(worker_iter); 554 workers_.erase(worker_iter);
491 } 555 }
492 worker_to_destroy->Cleanup(); 556 worker_to_destroy->Cleanup();
493 } 557 }
494 558
559 void SchedulerSingleThreadTaskRunnerManager::ReleaseSharedTaskRunners() {
560 decltype(shared_task_runners_) local_shared_task_runners;
561 #if defined(OS_WIN)
562 decltype(shared_com_task_runners_) local_shared_com_task_runners;
563 #endif
564 {
565 AutoSchedulerLock auto_lock(lock_);
566 for (size_t i = 0; i < arraysize(shared_task_runners_); ++i) {
567 local_shared_task_runners[i] = std::move(shared_task_runners_[i]);
568 #if defined(OS_WIN)
569 local_shared_com_task_runners[i] = std::move(shared_com_task_runners_[i]);
570 #endif
571 }
572 }
573 }
574
495 } // namespace internal 575 } // namespace internal
496 } // namespace base 576 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698