blob: 06df9100e70c891d4e9f3339cf743cff98025ebc [file] [log] [blame]
Brad Bishopc1283ae2017-05-20 21:42:38 -04001#pragma once
2
Brad Bishop3539db62017-05-30 14:21:12 -04003#include <chrono>
Brad Bishopc1283ae2017-05-20 21:42:38 -04004#include "data_types.hpp"
5
6namespace phosphor
7{
8namespace dbus
9{
10namespace monitoring
11{
12
13/** @class Callback
14 * @brief Callback interface.
15 *
16 * Callbacks of any type can be run.
17 */
18class Callback
19{
20 public:
21 Callback() = default;
22 Callback(const Callback&) = delete;
23 Callback(Callback&&) = default;
24 Callback& operator=(const Callback&) = delete;
25 Callback& operator=(Callback&&) = default;
26 virtual ~Callback() = default;
27
28 /** @brief Run the callback. */
29 virtual void operator()() = 0;
30};
31
Brad Bishop4041d722017-05-21 10:06:07 -040032/** @class Conditional
33 * @brief Condition interface.
34 *
35 * Conditions of any type can be tested for true or false.
36 */
37class Conditional
38{
39 public:
40 Conditional() = default;
41 Conditional(const Conditional&) = delete;
42 Conditional(Conditional&&) = default;
43 Conditional& operator=(const Conditional&) = delete;
44 Conditional& operator=(Conditional&&) = default;
45 virtual ~Conditional() = default;
46
47 /** @brief Test the condition. */
48 virtual bool operator()() = 0;
49};
50
51/** @class IndexedConditional
52 * @brief Condition with an index.
53 */
54class IndexedConditional : public Conditional
55{
56 public:
57 IndexedConditional() = delete;
58 IndexedConditional(const IndexedConditional&) = delete;
59 IndexedConditional(IndexedConditional&&) = default;
60 IndexedConditional& operator=(const IndexedConditional&) = delete;
61 IndexedConditional& operator=(IndexedConditional&&) = default;
62 virtual ~IndexedConditional() = default;
63
64 explicit IndexedConditional(const PropertyIndex& conditionIndex)
65 : Conditional(), index(conditionIndex) {}
66
67 /** @brief Test the condition. */
68 virtual bool operator()() override = 0;
69
70 protected:
71
72 /** @brief Property names and their associated storage. */
73 const PropertyIndex& index;
74};
75
Brad Bishopc1283ae2017-05-20 21:42:38 -040076/** @class IndexedCallback
77 * @brief Callback with an index.
78 */
79class IndexedCallback : public Callback
80{
81 public:
82 IndexedCallback() = delete;
83 IndexedCallback(const IndexedCallback&) = delete;
84 IndexedCallback(IndexedCallback&&) = default;
85 IndexedCallback& operator=(const IndexedCallback&) = delete;
86 IndexedCallback& operator=(IndexedCallback&&) = default;
87 virtual ~IndexedCallback() = default;
88 explicit IndexedCallback(const PropertyIndex& callbackIndex)
89 : Callback(), index(callbackIndex) {}
90
91 /** @brief Run the callback. */
92 virtual void operator()() override = 0;
93
94 protected:
95
96 /** @brief Property names and their associated storage. */
97 const PropertyIndex& index;
98};
99
Brad Bishop49e66172017-05-23 19:16:21 -0400100/** @class GroupOfCallbacks
101 * @brief Invoke multiple callbacks.
102 *
103 * A group of callbacks is implemented as a vector of array indicies
104 * into an external array of callbacks. The group function call
105 * operator traverses the vector of indicies, invoking each
106 * callback.
107 *
108 * @tparam CallbackAccess - Access to the array of callbacks.
109 */
110template <typename CallbackAccess>
111class GroupOfCallbacks : public Callback
112{
113 public:
114 GroupOfCallbacks() = delete;
115 GroupOfCallbacks(const GroupOfCallbacks&) = delete;
116 GroupOfCallbacks(GroupOfCallbacks&&) = default;
117 GroupOfCallbacks& operator=(const GroupOfCallbacks&) = delete;
118 GroupOfCallbacks& operator=(GroupOfCallbacks&&) = default;
119 ~GroupOfCallbacks() = default;
120 explicit GroupOfCallbacks(
121 const std::vector<size_t>& graphEntry)
122 : graph(graphEntry) {}
123
124 /** @brief Run the callbacks. */
125 void operator()() override
126 {
127 for (auto e : graph)
128 {
129 (*CallbackAccess::get()[e])();
130 }
131 }
132
133 private:
134 /** @brief The offsets of the callbacks in the group. */
135 const std::vector<size_t>& graph;
136};
137
Brad Bishop4041d722017-05-21 10:06:07 -0400138/** @class ConditionalCallback
139 * @brief Callback adaptor that asssociates a condition with a callback.
140 */
141template <typename CallbackAccess>
142class ConditionalCallback: public Callback
143{
144 public:
145 ConditionalCallback() = delete;
146 ConditionalCallback(const ConditionalCallback&) = delete;
147 ConditionalCallback(ConditionalCallback&&) = default;
148 ConditionalCallback& operator=(const ConditionalCallback&) = delete;
149 ConditionalCallback& operator=(ConditionalCallback&&) = default;
Brad Bishop3539db62017-05-30 14:21:12 -0400150 virtual ~ConditionalCallback() = default;
Brad Bishop4041d722017-05-21 10:06:07 -0400151 ConditionalCallback(
152 const std::vector<size_t>& graphEntry,
153 Conditional& cond)
154 : graph(graphEntry), condition(cond) {}
155
156 /** @brief Run the callback if the condition is satisfied. */
Brad Bishop3539db62017-05-30 14:21:12 -0400157 virtual void operator()() override
Brad Bishop4041d722017-05-21 10:06:07 -0400158 {
159 if (condition())
160 {
161 (*CallbackAccess::get()[graph[0]])();
162 }
163 }
164
Brad Bishop3539db62017-05-30 14:21:12 -0400165 protected:
Brad Bishop4041d722017-05-21 10:06:07 -0400166 /** @brief The index of the callback to conditionally invoke. */
167 const std::vector<size_t>& graph;
168
169 /** @brief The condition to test. */
170 Conditional& condition;
171};
172
Brad Bishop3539db62017-05-30 14:21:12 -0400173/** @class DeferrableCallback
174 *
175 * Deferrable callbacks wait a configurable period before
176 * invoking their associated callback.
177 *
178 * When the callback condition is initally met, start a timer. If the
179 * condition is tested again before the timer expires and it is not
180 * met cancel the timer. If the timer expires invoke the associated
181 * callback.
182 *
183 * @tparam CallbackAccess - Provide access to callback group instances.
184 * @tparam TimerType - Delegated timer access methods.
185 */
186template <typename CallbackAccess, typename TimerType>
187class DeferrableCallback : public ConditionalCallback<CallbackAccess>
188{
189 public:
190 DeferrableCallback() = delete;
191 DeferrableCallback(const DeferrableCallback&) = delete;
192 DeferrableCallback(DeferrableCallback&&) = default;
193 DeferrableCallback& operator=(const DeferrableCallback&) = delete;
194 DeferrableCallback& operator=(DeferrableCallback&&) = default;
195 ~DeferrableCallback() = default;
196
197 DeferrableCallback(
198 const std::vector<size_t>& graphEntry,
199 Conditional& cond,
200 const std::chrono::microseconds& delay)
201 : ConditionalCallback<CallbackAccess>(graphEntry, cond),
202 delayInterval(delay),
203 timer(nullptr) {}
204
205 void operator()() override
206 {
207 if (!timer)
208 {
209 timer = std::make_unique<TimerType>(
210// **INDENT-OFF**
211 [this](auto & source)
212 {
213 this->ConditionalCallback<CallbackAccess>::operator()();
214 });
215// **INDENT-ON**
216 timer->disable();
217 }
218
219 if (this->condition())
220 {
221 if (!timer->enabled())
222 {
223 // This is the first time the condition evaluated.
224 // Start the countdown.
225 timer->update(timer->now() + delayInterval);
226 timer->enable();
227 }
228 }
229 else
230 {
231 // The condition did not evaluate. Stop the countdown.
232 timer->disable();
233 }
234 }
235
236 private:
237 /** @brief The length to wait for the condition to stop evaluating. */
238 std::chrono::microseconds delayInterval;
239
240 /** @brief Delegated timer functions. */
241 std::unique_ptr<TimerType> timer;
242};
243
Brad Bishopc1283ae2017-05-20 21:42:38 -0400244} // namespace monitoring
245} // namespace dbus
246} // namespace phosphor