pw_async2: Derive TimeFuture from Future

As part of this, removes the `Reset` function from `TimeFuture`. A new
future should be acquired from the `TimeProvider` instead.

Change-Id: I236760eda4560448a293e6f3357775ca0fffc570
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/324492
Docs-Not-Needed: Alexei Frolov <frolv@google.com>
Reviewed-by: Lloyd Pique <lpique@google.com>
Commit-Queue: Alexei Frolov <frolv@google.com>
Lint: Lint 🤖 <android-build-ayeaye@system.gserviceaccount.com>
Presubmit-Verified: CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/pw_async2/public/pw_async2/time_provider.h b/pw_async2/public/pw_async2/time_provider.h
index 479e284..5ded953 100644
--- a/pw_async2/public/pw_async2/time_provider.h
+++ b/pw_async2/public/pw_async2/time_provider.h
@@ -19,6 +19,7 @@
 #include <mutex>
 
 #include "pw_async2/dispatcher.h"
+#include "pw_async2/future.h"
 #include "pw_chrono/virtual_clock.h"
 #include "pw_containers/intrusive_list.h"
 #include "pw_sync/interrupt_spin_lock.h"
@@ -119,7 +120,9 @@
 /// used with any `TimeProvider` with a compatible `Clock` type.
 template <typename Clock>
 class [[nodiscard]] TimeFuture
-    : public IntrusiveForwardList<TimeFuture<Clock>>::Item {
+    : public experimental::Future<TimeFuture<Clock>,
+                                  typename Clock::time_point>,
+      public IntrusiveForwardList<TimeFuture<Clock>>::Item {
  public:
   TimeFuture() : provider_(nullptr) {}
   TimeFuture(const TimeFuture&) = delete;
@@ -157,28 +160,6 @@
   /// Destruction is thread-safe, but not necessarily interrupt-safe.
   ~TimeFuture() { Unlist(); }
 
-  Poll<typename Clock::time_point> Pend(Context& cx)
-      PW_LOCKS_EXCLUDED(internal::time_lock()) {
-    std::lock_guard lock(internal::time_lock());
-    if (this->unlisted()) {
-      return Ready(expiration_);
-    }
-    // NOTE: this is done under the lock in order to ensure that `provider_` is
-    // not set to unlisted between it being initially read and `waker_` being
-    // set.
-    PW_ASYNC_STORE_WAKER(cx, waker_, "TimeFuture is waiting for a time_point");
-    return Pending();
-  }
-
-  /// Resets ``TimeFuture`` to expire at ``expiration``.
-  void Reset(typename Clock::time_point expiration)
-      PW_LOCKS_EXCLUDED(internal::time_lock()) {
-    std::lock_guard lock(internal::time_lock());
-    UnlistLocked();
-    expiration_ = expiration;
-    EnlistLocked();
-  }
-
   // Returns the provider associated with this timer.
   //
   // NOTE: this method must not be called before initializing the timer.
@@ -200,8 +181,34 @@
   }
 
  private:
+  using Base =
+      experimental::Future<TimeFuture<Clock>, typename Clock::time_point>;
+  friend Base;
   friend class TimeProvider<Clock>;
 
+  Poll<typename Clock::time_point> DoPend(Context& cx)
+      PW_LOCKS_EXCLUDED(internal::time_lock()) {
+    std::lock_guard lock(internal::time_lock());
+    if (this->unlisted()) {
+      return Ready(expiration_);
+    }
+    // NOTE: this is done under the lock in order to ensure that `provider_` is
+    // not set to unlisted between it being initially read and `waker_` being
+    // set.
+    PW_ASYNC_STORE_WAKER(cx, waker_, "TimeFuture is waiting for a time_point");
+    return Pending();
+  }
+
+  void DoMarkComplete() {
+    std::lock_guard lock(internal::time_lock());
+    provider_ = nullptr;
+  }
+
+  // SAFETY: It is safe to read `provider_` without holding the lock.
+  bool DoIsComplete() const PW_NO_LOCK_SAFETY_ANALYSIS {
+    return provider_ == nullptr;
+  }
+
   /// Constructs a `Timer` from a `TimeProvider` and a `time_point`.
   TimeFuture(TimeProvider<Clock>& provider,
              typename Clock::time_point expiration)
diff --git a/pw_async2/simulated_time_provider_test.cc b/pw_async2/simulated_time_provider_test.cc
index 8c191df..f0fe7e0 100644
--- a/pw_async2/simulated_time_provider_test.cc
+++ b/pw_async2/simulated_time_provider_test.cc
@@ -120,20 +120,6 @@
   EXPECT_FALSE(tp.TimeUntilNextExpiration().has_value());
 }
 
-TEST(SimulatedTimeProvider, ResetSetsTimerBackToPendingAndFiresAgain) {
-  SimulatedTimeProvider<SystemClock> tp;
-  Dispatcher dispatcher;
-
-  auto timer = tp.WaitFor(1h);
-  EXPECT_TRUE(dispatcher.RunPendableUntilStalled(timer).IsPending());
-  tp.AdvanceTime(90min);
-  EXPECT_TRUE(dispatcher.RunPendableUntilStalled(timer).IsReady());
-  timer.Reset(timer.expiration() + 40min);
-  EXPECT_TRUE(dispatcher.RunPendableUntilStalled(timer).IsPending());
-  tp.AdvanceTime(90min);
-  EXPECT_TRUE(dispatcher.RunPendableUntilStalled(timer).IsReady());
-}
-
 TEST(SimulatedTimeProvider, TimerWithPastExpirationExpiresImmediately) {
   SimulatedTimeProvider<SystemClock> tp;
   auto start = tp.now();