TaskQueueBase: Add PostDelayedHighPrecisionTask().

As per go/postdelayedtask-precision-in-webrtc we want to reduce the
precision of PostDelayedTask() in order to schedule work on the CPU
more efficiently. In order not to break "high precision" use cases, a
new API is added to allow opting in to high precision.

PostDelayedHighPrecisionTask() has the same precision that
PostDelayedTask() has today, but by changing the interface's
requirements on PostDelayedTask(), adding the high precision version
of it will unblock making the old PostDelayedTask() API lower
precision.

This CL does not update implementations to support low precision so
until those are updated, both PostDelayedTask() and
PostDelayedHighPrecisionTask() have the same precision (=high).

This CL also adds TODOs to make some rtc::Thread-specific versions
of PostTask/PostDelayedTask obsolete, see
https://crbug.com/webrtc/13582 for more info.

Bug: webrtc:13583, webrtc:13582
Change-Id: I4c6d53d22bb299c49893ce9f3ef73a40d8c75de1
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/247367
Reviewed-by: Markus Handell <handellm@webrtc.org>
Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35748}
diff --git a/api/task_queue/task_queue_base.h b/api/task_queue/task_queue_base.h
index d8af6e6..df422dc 100644
--- a/api/task_queue/task_queue_base.h
+++ b/api/task_queue/task_queue_base.h
@@ -11,6 +11,7 @@
 #define API_TASK_QUEUE_TASK_QUEUE_BASE_H_
 
 #include <memory>
+#include <utility>
 
 #include "api/task_queue/queued_task.h"
 #include "rtc_base/system/rtc_export.h"
@@ -48,14 +49,55 @@
   // May be called on any thread or task queue, including this task queue.
   virtual void PostTask(std::unique_ptr<QueuedTask> task) = 0;
 
+  // Prefer PostDelayedTask() over PostDelayedHighPrecisionTask() whenever
+  // possible.
+  //
   // Schedules a task to execute a specified number of milliseconds from when
-  // the call is made. The precision should be considered as "best effort"
-  // and in some cases, such as on Windows when all high precision timers have
-  // been used up, can be off by as much as 15 millseconds.
+  // the call is made, using "low" precision. All scheduling is affected by
+  // OS-specific leeway and current workloads which means that in terms of
+  // precision there are no hard guarantees, but in addition to the OS induced
+  // leeway, "low" precision adds up to a 17 ms additional leeway. The purpose
+  // of this leeway is to achieve more efficient CPU scheduling and reduce Idle
+  // Wake Up frequency.
+  //
+  // The task may execute with [-1, 17 + OS induced leeway) ms additional delay.
+  //
+  // Avoid making assumptions about the precision of the OS scheduler. On macOS,
+  // the OS induced leeway may be 10% of sleep interval. On Windows, 1 ms
+  // precision timers may be used but there are cases, such as when running on
+  // battery, when the timer precision can be as poor as 15 ms.
+  //
+  // "Low" precision is not implemented everywhere yet. Where not yet
+  // implemented, PostDelayedTask() has "high" precision. See
+  // https://crbug.com/webrtc/13583 for more information.
+  //
   // May be called on any thread or task queue, including this task queue.
   virtual void PostDelayedTask(std::unique_ptr<QueuedTask> task,
                                uint32_t milliseconds) = 0;
 
+  // Prefer PostDelayedTask() over PostDelayedHighPrecisionTask() whenever
+  // possible.
+  //
+  // Schedules a task to execute a specified number of milliseconds from when
+  // the call is made, using "high" precision. All scheduling is affected by
+  // OS-specific leeway and current workloads which means that in terms of
+  // precision there are no hard guarantees.
+  //
+  // The task may execute with [-1, OS induced leeway] ms additional delay.
+  //
+  // Avoid making assumptions about the precision of the OS scheduler. On macOS,
+  // the OS induced leeway may be 10% of sleep interval. On Windows, 1 ms
+  // precision timers may be used but there are cases, such as when running on
+  // battery, when the timer precision can be as poor as 15 ms.
+  //
+  // May be called on any thread or task queue, including this task queue.
+  virtual void PostDelayedHighPrecisionTask(std::unique_ptr<QueuedTask> task,
+                                            uint32_t milliseconds) {
+    // Remove default implementation when dependencies have implemented this
+    // method.
+    PostDelayedTask(std::move(task), milliseconds);
+  }
+
   // Returns the task queue that is running the current thread.
   // Returns nullptr if this thread is not associated with any task queue.
   // May be called on any thread or task queue, including this task queue.
diff --git a/rtc_base/thread.cc b/rtc_base/thread.cc
index 2a79d82..4e649f3 100644
--- a/rtc_base/thread.cc
+++ b/rtc_base/thread.cc
@@ -1109,10 +1109,16 @@
 
 void Thread::PostDelayedTask(std::unique_ptr<webrtc::QueuedTask> task,
                              uint32_t milliseconds) {
+  // This implementation does not support low precision yet.
+  PostDelayedHighPrecisionTask(std::move(task), milliseconds);
+}
+
+void Thread::PostDelayedHighPrecisionTask(
+    std::unique_ptr<webrtc::QueuedTask> task,
+    uint32_t milliseconds) {
   // Though PostDelayed takes MessageData by raw pointer (last parameter),
   // it still takes it with ownership.
-  PostDelayed(RTC_FROM_HERE, milliseconds, &queued_task_handler_,
-              /*id=*/0,
+  PostDelayed(RTC_FROM_HERE, milliseconds, &queued_task_handler_, /*id=*/0,
               new ScopedMessageData<webrtc::QueuedTask>(std::move(task)));
 }
 
diff --git a/rtc_base/thread.h b/rtc_base/thread.h
index 70cafe0..b2f8e35 100644
--- a/rtc_base/thread.h
+++ b/rtc_base/thread.h
@@ -452,12 +452,19 @@
   // Example - Calling a lambda function:
   // thread->PostTask(RTC_FROM_HERE,
   //                  [&x, &y] { x.TrackComputations(y.Compute()); });
+  //
+  // TODO(https://crbug.com/webrtc/13582): Deprecate and remove in favor of the
+  // PostTask() method inherited from TaskQueueBase. Stop using it inside
+  // third_party/webrtc and add ABSL_DEPRECATED("bugs.webrtc.org/13582").
   template <class FunctorT>
   void PostTask(const Location& posted_from, FunctorT&& functor) {
     Post(posted_from, GetPostTaskMessageHandler(), /*id=*/0,
          new rtc_thread_internal::MessageWithFunctor<FunctorT>(
              std::forward<FunctorT>(functor)));
   }
+  // TODO(https://crbug.com/webrtc/13582): Deprecate and remove in favor of the
+  // PostTask() method inherited from TaskQueueBase. Stop using it inside
+  // third_party/webrtc and add ABSL_DEPRECATED("bugs.webrtc.org/13582").
   template <class FunctorT>
   void PostDelayedTask(const Location& posted_from,
                        FunctorT&& functor,
@@ -472,6 +479,8 @@
   void PostTask(std::unique_ptr<webrtc::QueuedTask> task) override;
   void PostDelayedTask(std::unique_ptr<webrtc::QueuedTask> task,
                        uint32_t milliseconds) override;
+  void PostDelayedHighPrecisionTask(std::unique_ptr<webrtc::QueuedTask> task,
+                                    uint32_t milliseconds) override;
   void Delete() override;
 
   // ProcessMessages will process I/O and dispatch messages until: