blob: a4bfec22970b4ca49cfacb2e88df797a4cf73142 [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);
// 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_