Coverage Report

Created: 2026-09-24 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpowerd/callback_manager.h
Line
Count
Source
1
#ifndef PRODUCTION_BORG_MGMT_NODE_PROXY_SAFEPOWER_SAFEPOWER_AGENT_CALLBACK_MANAGER_H_
2
#define PRODUCTION_BORG_MGMT_NODE_PROXY_SAFEPOWER_SAFEPOWER_AGENT_CALLBACK_MANAGER_H_
3
4
#include <memory>
5
#include <vector>
6
7
#include "absl/base/thread_annotations.h"
8
#include "absl/functional/any_invocable.h"
9
#include "absl/synchronization/mutex.h"
10
11
namespace safepower_agent {
12
13
class CallbackManager {
14
 private:
15
  struct HandleImpl;
16
17
 public:
18
  using Callback = absl::AnyInvocable<void() &&>;
19
20
  class [[nodiscard]] Handle {
21
   public:
22
    Handle() = default;
23
    ~Handle() = default;
24
25
    Handle(Handle&& other) = default;
26
    Handle& operator=(Handle&& other) = default;
27
28
    explicit Handle(std::shared_ptr<HandleImpl> impl);
29
30
    // Returns true if the callback is still queued or is currently executing.
31
    bool pending() const ABSL_LOCKS_EXCLUDED(impl_->mutex);
32
    // Returns true if the callback has fully finished executing.
33
    bool executed() const ABSL_LOCKS_EXCLUDED(impl_->mutex);
34
    // Attempts to cancel the callback. Returns true if successfully cancelled,
35
    // or false if the callback is already executing, already executed, or
36
    // already cancelled.
37
    bool TryCancel() ABSL_LOCKS_EXCLUDED(impl_->mutex);
38
    // Wait for the callback to either be cancelled or executed.
39
    // Wait is guaranteed to finish if TryCancel is called (and the callback
40
    // finishes executing if it was already running).
41
    void Wait() ABSL_LOCKS_EXCLUDED(impl_->mutex);
42
43
   private:
44
    std::shared_ptr<HandleImpl> impl_ = nullptr;
45
  };
46
47
2
  CallbackManager() = default;
48
0
  ~CallbackManager() = default;
49
50
  // Assumption: Callbacks do not query, cancel  or otherwise reference
51
  // any handles.
52
53
  Handle RunFirst(Callback callback) ABSL_LOCKS_EXCLUDED(mutex_);
54
  Handle RunLast(Callback callback) ABSL_LOCKS_EXCLUDED(mutex_);
55
  void RunCallbacks() ABSL_LOCKS_EXCLUDED(mutex_);
56
57
 private:
58
  enum class State {
59
    kPending,
60
    kExecuting,
61
    kExecuted,
62
    kCancelled,
63
  };
64
65
  struct HandleImpl {
66
    absl::Mutex mutex;
67
    Callback callback;
68
    State state ABSL_GUARDED_BY(mutex) = State::kPending;
69
  };
70
71
  static void RunCallbackIfValid(const std::weak_ptr<HandleImpl>& weak_handle);
72
73
  absl::Mutex mutex_;
74
  std::vector<std::weak_ptr<HandleImpl>> run_first_ ABSL_GUARDED_BY(mutex_);
75
  std::vector<std::weak_ptr<HandleImpl>> run_last_ ABSL_GUARDED_BY(mutex_);
76
};
77
78
}  // namespace safepower_agent
79
80
#endif  // PRODUCTION_BORG_MGMT_NODE_PROXY_SAFEPOWER_SAFEPOWER_AGENT_CALLBACK_MANAGER_H_