Add support for injecting Clock to RepeatingTaskHandle.
This will improve support for tests that use Clock as well as offer a way to remove use of Sleep() in the tests. Bug: none Change-Id: I25fd0c6fc1b52ec0c917e56fae6807b136213d8d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/175566 Commit-Queue: Tommi <tommi@webrtc.org> Reviewed-by: Sebastian Jansson <srte@webrtc.org> Cr-Commit-Position: refs/heads/master@{#31305}
This commit is contained in:
parent
3e9068a6b4
commit
532cac526c
@ -21,6 +21,7 @@ rtc_library("repeating_task") {
|
||||
"../../api/task_queue",
|
||||
"../../api/units:time_delta",
|
||||
"../../api/units:timestamp",
|
||||
"../../system_wrappers:system_wrappers",
|
||||
"../synchronization:sequence_checker",
|
||||
"//third_party/abseil-cpp/absl/memory",
|
||||
]
|
||||
|
||||
@ -17,11 +17,13 @@
|
||||
|
||||
namespace webrtc {
|
||||
namespace webrtc_repeating_task_impl {
|
||||
|
||||
RepeatingTaskBase::RepeatingTaskBase(TaskQueueBase* task_queue,
|
||||
TimeDelta first_delay)
|
||||
TimeDelta first_delay,
|
||||
Clock* clock)
|
||||
: task_queue_(task_queue),
|
||||
next_run_time_(Timestamp::Micros(rtc::TimeMicros()) + first_delay) {
|
||||
}
|
||||
clock_(clock),
|
||||
next_run_time_(clock_->CurrentTime() + first_delay) {}
|
||||
|
||||
RepeatingTaskBase::~RepeatingTaskBase() = default;
|
||||
|
||||
@ -39,7 +41,7 @@ bool RepeatingTaskBase::Run() {
|
||||
return true;
|
||||
|
||||
RTC_DCHECK(delay.IsFinite());
|
||||
TimeDelta lost_time = Timestamp::Micros(rtc::TimeMicros()) - next_run_time_;
|
||||
TimeDelta lost_time = clock_->CurrentTime() - next_run_time_;
|
||||
next_run_time_ += delay;
|
||||
delay -= lost_time;
|
||||
delay = std::max(delay, TimeDelta::Zero());
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include "api/task_queue/task_queue_base.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "api/units/timestamp.h"
|
||||
#include "system_wrappers/include/clock.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -27,7 +28,9 @@ class RepeatingTaskHandle;
|
||||
namespace webrtc_repeating_task_impl {
|
||||
class RepeatingTaskBase : public QueuedTask {
|
||||
public:
|
||||
RepeatingTaskBase(TaskQueueBase* task_queue, TimeDelta first_delay);
|
||||
RepeatingTaskBase(TaskQueueBase* task_queue,
|
||||
TimeDelta first_delay,
|
||||
Clock* clock);
|
||||
~RepeatingTaskBase() override;
|
||||
|
||||
void Stop();
|
||||
@ -38,6 +41,7 @@ class RepeatingTaskBase : public QueuedTask {
|
||||
bool Run() final;
|
||||
|
||||
TaskQueueBase* const task_queue_;
|
||||
Clock* const clock_;
|
||||
// This is always finite, except for the special case where it's PlusInfinity
|
||||
// to signal that the task should stop.
|
||||
Timestamp next_run_time_ RTC_GUARDED_BY(task_queue_);
|
||||
@ -49,8 +53,9 @@ class RepeatingTaskImpl final : public RepeatingTaskBase {
|
||||
public:
|
||||
RepeatingTaskImpl(TaskQueueBase* task_queue,
|
||||
TimeDelta first_delay,
|
||||
Closure&& closure)
|
||||
: RepeatingTaskBase(task_queue, first_delay),
|
||||
Closure&& closure,
|
||||
Clock* clock)
|
||||
: RepeatingTaskBase(task_queue, first_delay, clock),
|
||||
closure_(std::forward<Closure>(closure)) {
|
||||
static_assert(
|
||||
std::is_same<TimeDelta,
|
||||
@ -90,10 +95,11 @@ class RepeatingTaskHandle {
|
||||
// repeated task is owned by the TaskQueue.
|
||||
template <class Closure>
|
||||
static RepeatingTaskHandle Start(TaskQueueBase* task_queue,
|
||||
Closure&& closure) {
|
||||
Closure&& closure,
|
||||
Clock* clock = Clock::GetRealTimeClock()) {
|
||||
auto repeating_task = std::make_unique<
|
||||
webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
|
||||
task_queue, TimeDelta::Zero(), std::forward<Closure>(closure));
|
||||
task_queue, TimeDelta::Zero(), std::forward<Closure>(closure), clock);
|
||||
auto* repeating_task_ptr = repeating_task.get();
|
||||
task_queue->PostTask(std::move(repeating_task));
|
||||
return RepeatingTaskHandle(repeating_task_ptr);
|
||||
@ -102,12 +108,14 @@ class RepeatingTaskHandle {
|
||||
// DelayedStart is equivalent to Start except that the first invocation of the
|
||||
// closure will be delayed by the given amount.
|
||||
template <class Closure>
|
||||
static RepeatingTaskHandle DelayedStart(TaskQueueBase* task_queue,
|
||||
TimeDelta first_delay,
|
||||
Closure&& closure) {
|
||||
static RepeatingTaskHandle DelayedStart(
|
||||
TaskQueueBase* task_queue,
|
||||
TimeDelta first_delay,
|
||||
Closure&& closure,
|
||||
Clock* clock = Clock::GetRealTimeClock()) {
|
||||
auto repeating_task = std::make_unique<
|
||||
webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
|
||||
task_queue, first_delay, std::forward<Closure>(closure));
|
||||
task_queue, first_delay, std::forward<Closure>(closure), clock);
|
||||
auto* repeating_task_ptr = repeating_task.get();
|
||||
task_queue->PostDelayedTask(std::move(repeating_task), first_delay.ms());
|
||||
return RepeatingTaskHandle(repeating_task_ptr);
|
||||
|
||||
@ -44,6 +44,21 @@ class MockClosure {
|
||||
MOCK_METHOD(void, Delete, ());
|
||||
};
|
||||
|
||||
class MockTaskQueue : public TaskQueueBase {
|
||||
public:
|
||||
MockTaskQueue() : task_queue_setter_(this) {}
|
||||
|
||||
MOCK_METHOD(void, Delete, (), (override));
|
||||
MOCK_METHOD(void, PostTask, (std::unique_ptr<QueuedTask> task), (override));
|
||||
MOCK_METHOD(void,
|
||||
PostDelayedTask,
|
||||
(std::unique_ptr<QueuedTask> task, uint32_t milliseconds),
|
||||
(override));
|
||||
|
||||
private:
|
||||
CurrentTaskQueueSetter task_queue_setter_;
|
||||
};
|
||||
|
||||
class MoveOnlyClosure {
|
||||
public:
|
||||
explicit MoveOnlyClosure(MockClosure* mock) : mock_(mock) {}
|
||||
@ -228,4 +243,37 @@ TEST(RepeatingTaskTest, Example) {
|
||||
// task queue destruction and running the desctructor closure.
|
||||
}
|
||||
|
||||
TEST(RepeatingTaskTest, ClockIntegration) {
|
||||
std::unique_ptr<QueuedTask> delayed_task;
|
||||
uint32_t expected_ms = 0;
|
||||
SimulatedClock clock(Timestamp::Millis(0));
|
||||
|
||||
NiceMock<MockTaskQueue> task_queue;
|
||||
ON_CALL(task_queue, PostDelayedTask)
|
||||
.WillByDefault(
|
||||
Invoke([&delayed_task, &expected_ms](std::unique_ptr<QueuedTask> task,
|
||||
uint32_t milliseconds) {
|
||||
EXPECT_EQ(milliseconds, expected_ms);
|
||||
delayed_task = std::move(task);
|
||||
}));
|
||||
|
||||
expected_ms = 100;
|
||||
RepeatingTaskHandle handle = RepeatingTaskHandle::DelayedStart(
|
||||
&task_queue, TimeDelta::Millis(100),
|
||||
[&clock]() {
|
||||
EXPECT_EQ(Timestamp::Millis(100), clock.CurrentTime());
|
||||
// Simulate work happening for 10ms.
|
||||
clock.AdvanceTimeMilliseconds(10);
|
||||
return TimeDelta::Millis(100);
|
||||
},
|
||||
&clock);
|
||||
|
||||
clock.AdvanceTimeMilliseconds(100);
|
||||
QueuedTask* task_to_run = delayed_task.release();
|
||||
expected_ms = 90;
|
||||
EXPECT_FALSE(task_to_run->Run());
|
||||
EXPECT_NE(nullptr, delayed_task.get());
|
||||
handle.Stop();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user