| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 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 | |
| 5 #include "media/cast/test/fake_single_thread_task_runner.h" | |
| 6 | |
| 7 #include "base/location.h" | |
| 8 #include "base/logging.h" | |
| 9 #include "base/time/tick_clock.h" | |
| 10 | |
| 11 namespace media { | |
| 12 namespace cast { | |
| 13 namespace test { | |
| 14 | |
| 15 FakeSingleThreadTaskRunner::FakeSingleThreadTaskRunner( | |
| 16 base::SimpleTestTickClock* clock) | |
| 17 : clock_(clock), | |
| 18 fail_on_next_task_(false) {} | |
| 19 | |
| 20 FakeSingleThreadTaskRunner::~FakeSingleThreadTaskRunner() {} | |
| 21 | |
| 22 bool FakeSingleThreadTaskRunner::PostDelayedTask( | |
| 23 const tracked_objects::Location& from_here, | |
| 24 const base::Closure& task, | |
| 25 base::TimeDelta delay) { | |
| 26 if (fail_on_next_task_) { | |
| 27 LOG(FATAL) << "Infinite task posting loop detected. Possibly caused by " | |
| 28 << from_here.ToString() << " posting a task with delay " | |
| 29 << delay.InMicroseconds() << " usec."; | |
| 30 } | |
| 31 | |
| 32 CHECK_LE(base::TimeDelta(), delay); | |
| 33 const base::TimeTicks run_time = clock_->NowTicks() + delay; | |
| 34 | |
| 35 // If there are one or more tasks with the exact same run time, schedule this | |
| 36 // task to occur after them. This mimics the FIFO ordering behavior when | |
| 37 // scheduling delayed tasks to be run via base::MessageLoop in a | |
| 38 // multi-threaded application. | |
| 39 if (!tasks_.empty()) { | |
| 40 const auto after_it = tasks_.lower_bound( | |
| 41 TaskKey(run_time + base::TimeDelta::FromMicroseconds(1), 0)); | |
| 42 if (after_it != tasks_.begin()) { | |
| 43 auto it = after_it; | |
| 44 --it; | |
| 45 if (it->first.first == run_time) { | |
| 46 tasks_.insert( | |
| 47 after_it /* hint */, | |
| 48 std::make_pair(TaskKey(run_time, it->first.second + 1), task)); | |
| 49 return true; | |
| 50 } | |
| 51 } | |
| 52 } | |
| 53 | |
| 54 // No tasks have the exact same run time, so just do a simple insert. | |
| 55 tasks_.insert(std::make_pair(TaskKey(run_time, 0), task)); | |
| 56 return true; | |
| 57 } | |
| 58 | |
| 59 bool FakeSingleThreadTaskRunner::RunsTasksOnCurrentThread() const { | |
| 60 return true; | |
| 61 } | |
| 62 | |
| 63 void FakeSingleThreadTaskRunner::RunTasks() { | |
| 64 while (true) { | |
| 65 // Run all tasks equal or older than current time. | |
| 66 const auto it = tasks_.begin(); | |
| 67 if (it == tasks_.end()) | |
| 68 return; // No more tasks. | |
| 69 | |
| 70 if (clock_->NowTicks() < it->first.first) | |
| 71 return; | |
| 72 | |
| 73 const base::Closure task = it->second; | |
| 74 tasks_.erase(it); | |
| 75 task.Run(); | |
| 76 } | |
| 77 } | |
| 78 | |
| 79 void FakeSingleThreadTaskRunner::Sleep(base::TimeDelta t) { | |
| 80 CHECK_LE(base::TimeDelta(), t); | |
| 81 const base::TimeTicks run_until = clock_->NowTicks() + t; | |
| 82 | |
| 83 while (1) { | |
| 84 // Run up to 100000 tasks that were scheduled to run during the sleep | |
| 85 // period. 100000 should be enough for everybody (see comments below). | |
| 86 for (int i = 0; i < 100000; i++) { | |
| 87 const auto it = tasks_.begin(); | |
| 88 if (it == tasks_.end() || run_until < it->first.first) { | |
| 89 clock_->Advance(run_until - clock_->NowTicks()); | |
| 90 return; | |
| 91 } | |
| 92 | |
| 93 clock_->Advance(it->first.first - clock_->NowTicks()); | |
| 94 const base::Closure task = it->second; | |
| 95 tasks_.erase(it); | |
| 96 task.Run(); | |
| 97 } | |
| 98 | |
| 99 // If this point is reached, there's likely some sort of case where a new | |
| 100 // non-delayed task is being posted every time a task is popped and invoked | |
| 101 // from the queue. If that happens, set fail_on_next_task_ to true and throw | |
| 102 // an error when the next task is posted, where we might be able to identify | |
| 103 // the caller causing the problem via logging. | |
| 104 fail_on_next_task_ = true; | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 bool FakeSingleThreadTaskRunner::PostNonNestableDelayedTask( | |
| 109 const tracked_objects::Location& from_here, | |
| 110 const base::Closure& task, | |
| 111 base::TimeDelta delay) { | |
| 112 NOTIMPLEMENTED(); | |
| 113 return false; | |
| 114 } | |
| 115 | |
| 116 } // namespace test | |
| 117 } // namespace cast | |
| 118 } // namespace media | |
| OLD | NEW |