blob: 5f5507444cd63611ebab1bba35b5270c868cdb99 [file]
#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_