one_shot_event.cc 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // Copyright 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/one_shot_event.h"
  5. #include <stddef.h>
  6. #include <utility>
  7. #include "base/callback.h"
  8. #include "base/location.h"
  9. #include "base/task/single_thread_task_runner.h"
  10. #include "base/task/task_runner.h"
  11. #include "base/threading/thread_task_runner_handle.h"
  12. #include "base/time/time.h"
  13. namespace base {
  14. struct OneShotEvent::TaskInfo {
  15. TaskInfo() {}
  16. TaskInfo(const Location& from_here,
  17. scoped_refptr<SingleThreadTaskRunner> runner,
  18. OnceClosure task,
  19. const TimeDelta& delay)
  20. : from_here(from_here),
  21. runner(std::move(runner)),
  22. task(std::move(task)),
  23. delay(delay) {
  24. CHECK(this->runner.get()); // Detect mistakes with a decent stack frame.
  25. }
  26. TaskInfo(TaskInfo&&) = default;
  27. TaskInfo& operator=(TaskInfo&&) = default;
  28. Location from_here;
  29. scoped_refptr<SingleThreadTaskRunner> runner;
  30. OnceClosure task;
  31. TimeDelta delay;
  32. };
  33. OneShotEvent::OneShotEvent() : signaled_(false) {
  34. // It's acceptable to construct the OneShotEvent on one thread, but
  35. // immediately move it to another thread.
  36. thread_checker_.DetachFromThread();
  37. }
  38. OneShotEvent::OneShotEvent(bool signaled) : signaled_(signaled) {
  39. thread_checker_.DetachFromThread();
  40. }
  41. OneShotEvent::~OneShotEvent() {}
  42. void OneShotEvent::Post(const Location& from_here,
  43. OnceClosure task,
  44. scoped_refptr<SingleThreadTaskRunner> runner) const {
  45. PostImpl(from_here, std::move(task), std::move(runner), TimeDelta());
  46. }
  47. void OneShotEvent::PostDelayed(const Location& from_here,
  48. OnceClosure task,
  49. const TimeDelta& delay) const {
  50. PostImpl(from_here, std::move(task), ThreadTaskRunnerHandle::Get(), delay);
  51. }
  52. void OneShotEvent::Signal() {
  53. DCHECK(thread_checker_.CalledOnValidThread());
  54. CHECK(!signaled_) << "Only call Signal once.";
  55. signaled_ = true;
  56. // After this point, a call to Post() from one of the queued tasks
  57. // could proceed immediately, but the fact that this object is
  58. // single-threaded prevents that from being relevant.
  59. // Move tasks to a temporary to ensure no new ones are added.
  60. std::vector<TaskInfo> moved_tasks;
  61. std::swap(moved_tasks, tasks_);
  62. // We could randomize tasks in debug mode in order to check that
  63. // the order doesn't matter...
  64. for (TaskInfo& task : moved_tasks) {
  65. if (task.delay.is_zero())
  66. task.runner->PostTask(task.from_here, std::move(task.task));
  67. else
  68. task.runner->PostDelayedTask(task.from_here, std::move(task.task),
  69. task.delay);
  70. }
  71. DCHECK(tasks_.empty()) << "No new tasks should be added during task running!";
  72. }
  73. void OneShotEvent::PostImpl(const Location& from_here,
  74. OnceClosure task,
  75. scoped_refptr<SingleThreadTaskRunner> runner,
  76. const TimeDelta& delay) const {
  77. DCHECK(thread_checker_.CalledOnValidThread());
  78. if (is_signaled()) {
  79. if (delay.is_zero())
  80. runner->PostTask(from_here, std::move(task));
  81. else
  82. runner->PostDelayedTask(from_here, std::move(task), delay);
  83. } else {
  84. tasks_.emplace_back(from_here, std::move(runner), std::move(task), delay);
  85. }
  86. }
  87. } // namespace base