Refactor RepeatingTaskHandle to use absl::AnyInvocable

Allow to use AnyInvocable in webrtc.
Demonstrate how AnyInvocable can make interface clearer to read and implement
Demonstrate that AnyInvocable can reduce binary size

Bug: None
Change-Id: I33cf33fac6ed3bf4c5e46077d1cd984ca0f253a3
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/267165
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37380}
This commit is contained in:
Danil Chapovalov 2022-06-30 10:08:47 +02:00 committed by WebRTC LUCI CQ
parent 978cb6762f
commit 4b97928b30
5 changed files with 74 additions and 94 deletions

1
DEPS
View File

@ -2494,6 +2494,7 @@ include_rules = [
"+absl/base/macros.h",
"+absl/cleanup/cleanup.h",
"+absl/container/inlined_vector.h",
"+absl/functional/any_invocable.h",
"+absl/functional/bind_front.h",
"+absl/memory/memory.h",
"+absl/meta/type_traits.h",

View File

@ -25,6 +25,7 @@ will generate a shared library.
## **Allowed**
* `absl::AnyInvocable`
* `absl::bind_front`
* `absl::Cleanup`
* `absl::InlinedVector`

View File

@ -24,7 +24,10 @@ rtc_library("repeating_task") {
"../../api/units:timestamp",
"../../system_wrappers:system_wrappers",
]
absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
absl_deps = [
"//third_party/abseil-cpp/absl/functional:any_invocable",
"//third_party/abseil-cpp/absl/memory",
]
}
rtc_library("pending_task_safety_flag") {

View File

@ -10,6 +10,7 @@
#include "rtc_base/task_utils/repeating_task.h"
#include "absl/functional/any_invocable.h"
#include "absl/memory/memory.h"
#include "api/task_queue/pending_task_safety_flag.h"
#include "api/task_queue/to_queued_task.h"
@ -17,29 +18,53 @@
#include "rtc_base/time_utils.h"
namespace webrtc {
namespace webrtc_repeating_task_impl {
namespace {
RepeatingTaskBase::RepeatingTaskBase(
class RepeatingTask : public QueuedTask {
public:
RepeatingTask(TaskQueueBase* task_queue,
TaskQueueBase::DelayPrecision precision,
TimeDelta first_delay,
absl::AnyInvocable<TimeDelta()> task,
Clock* clock,
rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag);
~RepeatingTask() override = default;
private:
bool Run() final;
TaskQueueBase* const task_queue_;
const TaskQueueBase::DelayPrecision precision_;
Clock* const clock_;
absl::AnyInvocable<TimeDelta()> task_;
// This is always finite.
Timestamp next_run_time_ RTC_GUARDED_BY(task_queue_);
rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag_
RTC_GUARDED_BY(task_queue_);
};
RepeatingTask::RepeatingTask(
TaskQueueBase* task_queue,
TaskQueueBase::DelayPrecision precision,
TimeDelta first_delay,
absl::AnyInvocable<TimeDelta()> task,
Clock* clock,
rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag)
: task_queue_(task_queue),
precision_(precision),
clock_(clock),
task_(std::move(task)),
next_run_time_(clock_->CurrentTime() + first_delay),
alive_flag_(std::move(alive_flag)) {}
RepeatingTaskBase::~RepeatingTaskBase() = default;
bool RepeatingTaskBase::Run() {
bool RepeatingTask::Run() {
RTC_DCHECK_RUN_ON(task_queue_);
// Return true to tell the TaskQueue to destruct this object.
if (!alive_flag_->alive())
return true;
TimeDelta delay = RunClosure();
webrtc_repeating_task_impl::RepeatingTaskImplDTraceProbeRun();
TimeDelta delay = task_();
RTC_DCHECK_GE(delay, TimeDelta::Zero());
// A delay of +infinity means that the task should not be run again.
@ -61,7 +86,38 @@ bool RepeatingTaskBase::Run() {
return false;
}
} // namespace webrtc_repeating_task_impl
} // namespace
RepeatingTaskHandle RepeatingTaskHandle::Start(
TaskQueueBase* task_queue,
absl::AnyInvocable<TimeDelta()> closure,
TaskQueueBase::DelayPrecision precision,
Clock* clock) {
auto alive_flag = PendingTaskSafetyFlag::CreateDetached();
webrtc_repeating_task_impl::RepeatingTaskHandleDTraceProbeStart();
task_queue->PostTask(
std::make_unique<RepeatingTask>(task_queue, precision, TimeDelta::Zero(),
std::move(closure), clock, alive_flag));
return RepeatingTaskHandle(std::move(alive_flag));
}
// DelayedStart is equivalent to Start except that the first invocation of the
// closure will be delayed by the given amount.
RepeatingTaskHandle RepeatingTaskHandle::DelayedStart(
TaskQueueBase* task_queue,
TimeDelta first_delay,
absl::AnyInvocable<TimeDelta()> closure,
TaskQueueBase::DelayPrecision precision,
Clock* clock) {
auto alive_flag = PendingTaskSafetyFlag::CreateDetached();
webrtc_repeating_task_impl::RepeatingTaskHandleDTraceProbeDelayedStart();
task_queue->PostDelayedTaskWithPrecision(
precision,
std::make_unique<RepeatingTask>(task_queue, precision, first_delay,
std::move(closure), clock, alive_flag),
first_delay.ms());
return RepeatingTaskHandle(std::move(alive_flag));
}
void RepeatingTaskHandle::Stop() {
if (repeating_task_) {

View File

@ -15,11 +15,10 @@
#include <type_traits>
#include <utility>
#include "absl/functional/any_invocable.h"
#include "api/task_queue/pending_task_safety_flag.h"
#include "api/task_queue/queued_task.h"
#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 {
@ -31,64 +30,6 @@ void RepeatingTaskHandleDTraceProbeStart();
void RepeatingTaskHandleDTraceProbeDelayedStart();
void RepeatingTaskImplDTraceProbeRun();
class RepeatingTaskBase : public QueuedTask {
public:
RepeatingTaskBase(TaskQueueBase* task_queue,
TaskQueueBase::DelayPrecision precision,
TimeDelta first_delay,
Clock* clock,
rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag);
~RepeatingTaskBase() override;
private:
virtual TimeDelta RunClosure() = 0;
bool Run() final;
TaskQueueBase* const task_queue_;
const TaskQueueBase::DelayPrecision precision_;
Clock* const clock_;
// This is always finite.
Timestamp next_run_time_ RTC_GUARDED_BY(task_queue_);
rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag_
RTC_GUARDED_BY(task_queue_);
};
// The template closure pattern is based on rtc::ClosureTask. The provided
// closure should have a TimeDelta return value, specifing the desired
// non-negative interval to next repetition, or TimeDelta::PlusInfinity to
// indicate that the task should be deleted and not called again.
template <class Closure>
class RepeatingTaskImpl final : public RepeatingTaskBase {
public:
RepeatingTaskImpl(TaskQueueBase* task_queue,
TaskQueueBase::DelayPrecision precision,
TimeDelta first_delay,
Closure&& closure,
Clock* clock,
rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag)
: RepeatingTaskBase(task_queue,
precision,
first_delay,
clock,
std::move(alive_flag)),
closure_(std::forward<Closure>(closure)) {
static_assert(
std::is_same<TimeDelta,
typename std::invoke_result<decltype(&Closure::operator()),
Closure>::type>::value,
"");
}
private:
TimeDelta RunClosure() override {
RepeatingTaskImplDTraceProbeRun();
return closure_();
}
typename std::remove_const<
typename std::remove_reference<Closure>::type>::type closure_;
};
} // namespace webrtc_repeating_task_impl
// Allows starting tasks that repeat themselves on a TaskQueue indefinately
@ -111,43 +52,21 @@ class RepeatingTaskHandle {
// TaskQueue deletes it. It's perfectly fine to destroy the handle while the
// task is running, since the repeated task is owned by the TaskQueue.
// The tasks are scheduled onto the task queue using the specified precision.
template <class Closure>
static RepeatingTaskHandle Start(TaskQueueBase* task_queue,
Closure&& closure,
absl::AnyInvocable<TimeDelta()> closure,
TaskQueueBase::DelayPrecision precision =
TaskQueueBase::DelayPrecision::kLow,
Clock* clock = Clock::GetRealTimeClock()) {
auto alive_flag = PendingTaskSafetyFlag::CreateDetached();
webrtc_repeating_task_impl::RepeatingTaskHandleDTraceProbeStart();
task_queue->PostTask(
std::make_unique<
webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
task_queue, precision, TimeDelta::Zero(),
std::forward<Closure>(closure), clock, alive_flag));
return RepeatingTaskHandle(std::move(alive_flag));
}
Clock* clock = Clock::GetRealTimeClock());
// 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,
absl::AnyInvocable<TimeDelta()> closure,
TaskQueueBase::DelayPrecision precision =
TaskQueueBase::DelayPrecision::kLow,
Clock* clock = Clock::GetRealTimeClock()) {
auto alive_flag = PendingTaskSafetyFlag::CreateDetached();
webrtc_repeating_task_impl::RepeatingTaskHandleDTraceProbeDelayedStart();
task_queue->PostDelayedTaskWithPrecision(
precision,
std::make_unique<
webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
task_queue, precision, first_delay, std::forward<Closure>(closure),
clock, alive_flag),
first_delay.ms());
return RepeatingTaskHandle(std::move(alive_flag));
}
Clock* clock = Clock::GetRealTimeClock());
// Stops future invocations of the repeating task closure. Can only be called
// from the TaskQueue where the task is running. The closure is guaranteed to