| #ifndef PRODUCTION_BORG_MGMT_NODE_PROXY_SAFEPOWER_SAFEPOWER_AGENT_CALLBACK_MANAGER_H_ |
| #define PRODUCTION_BORG_MGMT_NODE_PROXY_SAFEPOWER_SAFEPOWER_AGENT_CALLBACK_MANAGER_H_ |
| |
| #include <memory> |
| #include <vector> |
| |
| #include "absl/base/thread_annotations.h" |
| #include "absl/functional/any_invocable.h" |
| #include "absl/synchronization/mutex.h" |
| |
| namespace safepower_agent { |
| |
| class CallbackManager { |
| private: |
| struct HandleImpl; |
| |
| public: |
| using Callback = absl::AnyInvocable<void() &&>; |
| |
| class [[nodiscard]] Handle { |
| public: |
| Handle() = default; |
| ~Handle() = default; |
| |
| Handle(Handle&& other) = default; |
| Handle& operator=(Handle&& other) = default; |
| |
| explicit Handle(std::shared_ptr<HandleImpl> impl); |
| |
| // Returns true if the callback is still queued or is currently executing. |
| bool pending() const ABSL_LOCKS_EXCLUDED(impl_->mutex); |
| // Returns true if the callback has fully finished executing. |
| bool executed() const ABSL_LOCKS_EXCLUDED(impl_->mutex); |
| // Attempts to cancel the callback. Returns true if successfully cancelled, |
| // or false if the callback is already executing, already executed, or |
| // already cancelled. |
| bool TryCancel() ABSL_LOCKS_EXCLUDED(impl_->mutex); |
| // Wait for the callback to either be cancelled or executed. |
| // Wait is guaranteed to finish if TryCancel is called (and the callback |
| // finishes executing if it was already running). |
| void Wait() ABSL_LOCKS_EXCLUDED(impl_->mutex); |
| |
| private: |
| std::shared_ptr<HandleImpl> impl_ = nullptr; |
| }; |
| |
| CallbackManager() = default; |
| ~CallbackManager() = default; |
| |
| // Assumption: Callbacks do not query, cancel or otherwise reference |
| // any handles. |
| |
| Handle RunFirst(Callback callback) ABSL_LOCKS_EXCLUDED(mutex_); |
| Handle RunLast(Callback callback) ABSL_LOCKS_EXCLUDED(mutex_); |
| void RunCallbacks() ABSL_LOCKS_EXCLUDED(mutex_); |
| |
| private: |
| enum class State { |
| kPending, |
| kExecuting, |
| kExecuted, |
| kCancelled, |
| }; |
| |
| struct HandleImpl { |
| absl::Mutex mutex; |
| Callback callback; |
| State state ABSL_GUARDED_BY(mutex) = State::kPending; |
| }; |
| |
| static void RunCallbackIfValid(const std::weak_ptr<HandleImpl>& weak_handle); |
| |
| absl::Mutex mutex_; |
| std::vector<std::weak_ptr<HandleImpl>> run_first_ ABSL_GUARDED_BY(mutex_); |
| std::vector<std::weak_ptr<HandleImpl>> run_last_ ABSL_GUARDED_BY(mutex_); |
| }; |
| |
| } // namespace safepower_agent |
| |
| #endif // PRODUCTION_BORG_MGMT_NODE_PROXY_SAFEPOWER_SAFEPOWER_AGENT_CALLBACK_MANAGER_H_ |