21#include "pw_async2/dispatcher.h"
22#include "pw_chrono/virtual_clock.h"
23#include "pw_containers/intrusive_list.h"
24#include "pw_sync/interrupt_spin_lock.h"
25#include "pw_sync/lock_annotations.h"
26#include "pw_toolchain/no_destructor.h"
39void AssertTimeFutureObjectsAllGone(
bool empty);
43template <
typename Clock>
59template <
typename Clock>
63 internal::AssertTimeFutureObjectsAllGone(futures_.empty());
66 typename Clock::time_point
now()
override = 0;
77 return WaitUntil(
now() + delay +
typename Clock::duration(1));
85 typename Clock::time_point timestamp) {
95 PW_LOCKS_EXCLUDED(internal::time_lock());
103 PW_EXCLUSIVE_LOCKS_REQUIRED(internal::time_lock()) = 0;
107 PW_EXCLUSIVE_LOCKS_REQUIRED(internal::time_lock()) = 0;
111 PW_GUARDED_BY(internal::time_lock());
118template <typename Clock>
127 *
this = std::move(other);
131 std::lock_guard lock(internal::time_lock());
134 provider_ = other.provider_;
135 expiration_ = other.expiration_;
138 if (!other.unlisted()) {
139 auto previous = provider_->futures_.before_begin();
140 while (&*std::next(previous) != &other) {
146 other.unlist(&*previous);
147 provider_->futures_.insert_after(previous, *
this);
159 PW_LOCKS_EXCLUDED(internal::time_lock()) {
160 std::lock_guard lock(internal::time_lock());
161 if (this->unlisted()) {
162 return Ready(expiration_);
167 PW_ASYNC_STORE_WAKER(cx, waker_,
"TimeFuture is waiting for a time_point");
172 void Reset(
typename Clock::time_point expiration)
173 PW_LOCKS_EXCLUDED(internal::time_lock()) {
174 std::lock_guard lock(internal::time_lock());
176 expiration_ = expiration;
194 typename Clock::time_point expiration() PW_NO_LOCK_SAFETY_ANALYSIS {
201 friend class TimeProvider<Clock>;
204 TimeFuture(TimeProvider<Clock>& provider,
205 typename Clock::time_point expiration)
206 : waker_(), provider_(&provider), expiration_(expiration) {
207 std::lock_guard lock(internal::time_lock());
211 void EnlistLocked() PW_EXCLUSIVE_LOCKS_REQUIRED(internal::time_lock()) {
215 if (provider_->now() >= expiration_) {
219 if (provider_->futures_.empty() ||
220 provider_->futures_.front().expiration_ > expiration_) {
221 provider_->futures_.push_front(*
this);
222 provider_->DoInvokeAt(expiration_);
225 auto current = provider_->futures_.begin();
226 while (std::next(current) != provider_->futures_.end() &&
227 std::next(current)->expiration_ < expiration_) {
230 provider_->futures_.insert_after(current, *
this);
233 void Unlist() PW_LOCKS_EXCLUDED(internal::time_lock()) {
234 std::lock_guard lock(internal::time_lock());
243 void UnlistLocked() PW_EXCLUSIVE_LOCKS_REQUIRED(internal::time_lock()) {
244 if (this->unlisted()) {
247 if (&provider_->futures_.front() ==
this) {
248 provider_->futures_.pop_front();
249 if (provider_->futures_.empty()) {
250 provider_->DoCancel();
252 provider_->DoInvokeAt(provider_->futures_.front().expiration_);
257 provider_->futures_.remove(*
this);
268 TimeProvider<Clock>* provider_ PW_GUARDED_BY(internal::time_lock());
269 typename Clock::time_point expiration_ PW_GUARDED_BY(internal::time_lock());
272template <
typename Clock>
274 std::lock_guard lock(internal::time_lock());
275 while (!futures_.empty()) {
276 if (futures_.front().expiration_ >
now) {
280 std::move(futures_.front().waker_).Wake();
281 futures_.pop_front();
Definition: intrusive_forward_list.h:86
Definition: dispatcher_base.h:52
Definition: time_provider.h:120
~TimeFuture()
Definition: time_provider.h:156
void Reset(typename Clock::time_point expiration)
Resets TimeFuture to expire at expiration.
Definition: time_provider.h:172
Definition: time_provider.h:60
virtual void DoCancel()=0
Optimistically cancels all pending DoInvokeAt requests.
Clock::time_point now() override=0
Returns the current time.
TimeFuture< Clock > WaitFor(typename Clock::duration delay)
Definition: time_provider.h:72
virtual void DoInvokeAt(typename Clock::time_point)=0
TimeFuture< Clock > WaitUntil(typename Clock::time_point timestamp)
Definition: time_provider.h:84
void RunExpired(typename Clock::time_point now)
Definition: time_provider.h:273
Definition: virtual_clock.h:29
Definition: intrusive_list.h:82
Definition: interrupt_spin_lock.h:48