|
|
|
@ -17,14 +17,12 @@ |
|
|
|
|
|
|
|
|
|
#include <grpc/support/port_platform.h> |
|
|
|
|
|
|
|
|
|
#include <utility> |
|
|
|
|
|
|
|
|
|
#include "absl/base/thread_annotations.h" |
|
|
|
|
#include "absl/status/status.h" |
|
|
|
|
|
|
|
|
|
#include <grpc/event_engine/event_engine.h> |
|
|
|
|
#include <grpc/support/log.h> |
|
|
|
|
|
|
|
|
|
#include "src/core/lib/gprpp/sync.h" |
|
|
|
|
#include "src/core/lib/gprpp/ref_counted.h" |
|
|
|
|
#include "src/core/lib/gprpp/time.h" |
|
|
|
|
#include "src/core/lib/promise/activity.h" |
|
|
|
|
#include "src/core/lib/promise/poll.h" |
|
|
|
@ -32,43 +30,48 @@ |
|
|
|
|
namespace grpc_core { |
|
|
|
|
|
|
|
|
|
// Promise that sleeps until a deadline and then finishes.
|
|
|
|
|
class Sleep { |
|
|
|
|
class Sleep final { |
|
|
|
|
public: |
|
|
|
|
explicit Sleep(Timestamp deadline); |
|
|
|
|
~Sleep(); |
|
|
|
|
|
|
|
|
|
Sleep(const Sleep&) = delete; |
|
|
|
|
Sleep& operator=(const Sleep&) = delete; |
|
|
|
|
Sleep(Sleep&& other) noexcept |
|
|
|
|
: deadline_(other.deadline_), timer_handle_(other.timer_handle_) { |
|
|
|
|
MutexLock lock2(&other.mu_); |
|
|
|
|
stage_ = other.stage_; |
|
|
|
|
waker_ = std::move(other.waker_); |
|
|
|
|
other.deadline_ = Timestamp::InfPast(); |
|
|
|
|
Sleep(Sleep&& other) noexcept : deadline_(other.deadline_) { |
|
|
|
|
// Promises can be moved only until they're polled, and since we only create
|
|
|
|
|
// the closure when first polled we can assume it's nullptr here.
|
|
|
|
|
GPR_DEBUG_ASSERT(other.closure_ == nullptr); |
|
|
|
|
}; |
|
|
|
|
Sleep& operator=(Sleep&& other) noexcept { |
|
|
|
|
if (&other == this) return *this; |
|
|
|
|
MutexLock lock1(&mu_); |
|
|
|
|
MutexLock lock2(&other.mu_); |
|
|
|
|
// Promises can be moved only until they're polled, and since we only create
|
|
|
|
|
// the closure when first polled we can assume it's nullptr here.
|
|
|
|
|
GPR_DEBUG_ASSERT(closure_ == nullptr); |
|
|
|
|
GPR_DEBUG_ASSERT(other.closure_ == nullptr); |
|
|
|
|
deadline_ = other.deadline_; |
|
|
|
|
timer_handle_ = other.timer_handle_; |
|
|
|
|
stage_ = other.stage_; |
|
|
|
|
waker_ = std::move(other.waker_); |
|
|
|
|
other.deadline_ = Timestamp::InfPast(); |
|
|
|
|
return *this; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
Poll<absl::Status> operator()(); |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
enum class Stage { kInitial, kStarted, kDone }; |
|
|
|
|
void OnTimer(); |
|
|
|
|
class ActiveClosure final |
|
|
|
|
: public grpc_event_engine::experimental::EventEngine::Closure { |
|
|
|
|
public: |
|
|
|
|
explicit ActiveClosure(Timestamp deadline); |
|
|
|
|
|
|
|
|
|
void Run() override; |
|
|
|
|
void Cancel(); |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
Waker waker_; |
|
|
|
|
// One ref dropped by Run(), the other by Cancel().
|
|
|
|
|
RefCount refs_{2}; |
|
|
|
|
const grpc_event_engine::experimental::EventEngine::TaskHandle |
|
|
|
|
timer_handle_; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
Timestamp deadline_; |
|
|
|
|
grpc_event_engine::experimental::EventEngine::TaskHandle timer_handle_; |
|
|
|
|
Mutex mu_; |
|
|
|
|
Stage stage_ ABSL_GUARDED_BY(mu_) = Stage::kInitial; |
|
|
|
|
Waker waker_ ABSL_GUARDED_BY(mu_); |
|
|
|
|
ActiveClosure* closure_{nullptr}; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
} // namespace grpc_core
|
|
|
|
|