| #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); |
| |
| bool pending() const ABSL_LOCKS_EXCLUDED(impl_->mutex); |
| bool TryCancel() 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: |
| struct HandleImpl { |
| absl::Mutex mutex; |
| Callback callback; |
| }; |
| |
| 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_ |