blob: 26cd2a17c785b63ce5a42d8db5cd8318ed362df9 [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{
Brad Bishopd1eac882018-03-29 10:34:05 -040020 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;
Brad Bishopc1283ae2017-05-20 21:42:38 -040027
Brad Bishopd1eac882018-03-29 10:34:05 -040028 /** @brief Run the callback.
29 * @param[in] ctx - caller context
30 * Context could be Startup or Signal
31 * Startup: Callback is called as part of process startup.
32 * Signal: Callback is called as part of watch condition has been met.
33 *
34 */
35 virtual void operator()(Context ctx) = 0;
Brad Bishopc1283ae2017-05-20 21:42:38 -040036};
37
Brad Bishop4041d722017-05-21 10:06:07 -040038/** @class Conditional
39 * @brief Condition interface.
40 *
41 * Conditions of any type can be tested for true or false.
42 */
43class Conditional
44{
Brad Bishopd1eac882018-03-29 10:34:05 -040045 public:
46 Conditional() = default;
47 Conditional(const Conditional&) = delete;
48 Conditional(Conditional&&) = default;
49 Conditional& operator=(const Conditional&) = delete;
50 Conditional& operator=(Conditional&&) = default;
51 virtual ~Conditional() = default;
Brad Bishop4041d722017-05-21 10:06:07 -040052
Brad Bishopd1eac882018-03-29 10:34:05 -040053 /** @brief Test the condition. */
54 virtual bool operator()() = 0;
Brad Bishop4041d722017-05-21 10:06:07 -040055};
56
57/** @class IndexedConditional
58 * @brief Condition with an index.
59 */
60class IndexedConditional : public Conditional
61{
Brad Bishopd1eac882018-03-29 10:34:05 -040062 public:
63 IndexedConditional() = delete;
64 IndexedConditional(const IndexedConditional&) = delete;
65 IndexedConditional(IndexedConditional&&) = default;
66 IndexedConditional& operator=(const IndexedConditional&) = delete;
67 IndexedConditional& operator=(IndexedConditional&&) = default;
68 virtual ~IndexedConditional() = default;
Brad Bishop4041d722017-05-21 10:06:07 -040069
Brad Bishopd1eac882018-03-29 10:34:05 -040070 explicit IndexedConditional(const PropertyIndex& conditionIndex) :
71 Conditional(), index(conditionIndex)
72 {
73 }
Brad Bishop4041d722017-05-21 10:06:07 -040074
Brad Bishopd1eac882018-03-29 10:34:05 -040075 /** @brief Test the condition. */
76 virtual bool operator()() override = 0;
Brad Bishop4041d722017-05-21 10:06:07 -040077
Brad Bishopd1eac882018-03-29 10:34:05 -040078 protected:
79 /** @brief Property names and their associated storage. */
80 const PropertyIndex& index;
Brad Bishop4041d722017-05-21 10:06:07 -040081};
82
Brad Bishopc1283ae2017-05-20 21:42:38 -040083/** @class IndexedCallback
84 * @brief Callback with an index.
85 */
86class IndexedCallback : public Callback
87{
Brad Bishopd1eac882018-03-29 10:34:05 -040088 public:
89 IndexedCallback() = delete;
90 IndexedCallback(const IndexedCallback&) = delete;
91 IndexedCallback(IndexedCallback&&) = default;
92 IndexedCallback& operator=(const IndexedCallback&) = delete;
93 IndexedCallback& operator=(IndexedCallback&&) = default;
94 virtual ~IndexedCallback() = default;
95 explicit IndexedCallback(const PropertyIndex& callbackIndex) :
96 Callback(), index(callbackIndex)
97 {
98 }
Brad Bishopc1283ae2017-05-20 21:42:38 -040099
Brad Bishopd1eac882018-03-29 10:34:05 -0400100 /** @brief Run the callback. */
101 virtual void operator()(Context ctx) override = 0;
Brad Bishopc1283ae2017-05-20 21:42:38 -0400102
Brad Bishopd1eac882018-03-29 10:34:05 -0400103 protected:
104 /** @brief Property names and their associated storage. */
105 const PropertyIndex& index;
Brad Bishopc1283ae2017-05-20 21:42:38 -0400106};
107
Brad Bishop49e66172017-05-23 19:16:21 -0400108/** @class GroupOfCallbacks
109 * @brief Invoke multiple callbacks.
110 *
Gunnar Mills78199b42017-10-25 16:30:18 -0500111 * A group of callbacks is implemented as a vector of array indices
Brad Bishop49e66172017-05-23 19:16:21 -0400112 * into an external array of callbacks. The group function call
Gunnar Mills78199b42017-10-25 16:30:18 -0500113 * operator traverses the vector of indices, invoking each
Brad Bishop49e66172017-05-23 19:16:21 -0400114 * callback.
115 *
116 * @tparam CallbackAccess - Access to the array of callbacks.
117 */
Brad Bishopd1eac882018-03-29 10:34:05 -0400118template <typename CallbackAccess> class GroupOfCallbacks : public Callback
Brad Bishop49e66172017-05-23 19:16:21 -0400119{
Brad Bishopd1eac882018-03-29 10:34:05 -0400120 public:
121 GroupOfCallbacks() = delete;
122 GroupOfCallbacks(const GroupOfCallbacks&) = delete;
123 GroupOfCallbacks(GroupOfCallbacks&&) = default;
124 GroupOfCallbacks& operator=(const GroupOfCallbacks&) = delete;
125 GroupOfCallbacks& operator=(GroupOfCallbacks&&) = default;
126 ~GroupOfCallbacks() = default;
127 explicit GroupOfCallbacks(const std::vector<size_t>& graphEntry) :
128 graph(graphEntry)
129 {
130 }
Brad Bishop49e66172017-05-23 19:16:21 -0400131
Brad Bishopd1eac882018-03-29 10:34:05 -0400132 /** @brief Run the callbacks. */
133 void operator()(Context ctx) override
134 {
135 for (auto e : graph)
Brad Bishop49e66172017-05-23 19:16:21 -0400136 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400137 (*CallbackAccess::get()[e])(ctx);
Brad Bishop49e66172017-05-23 19:16:21 -0400138 }
Brad Bishopd1eac882018-03-29 10:34:05 -0400139 }
Brad Bishop49e66172017-05-23 19:16:21 -0400140
Brad Bishopd1eac882018-03-29 10:34:05 -0400141 private:
142 /** @brief The offsets of the callbacks in the group. */
143 const std::vector<size_t>& graph;
Brad Bishop49e66172017-05-23 19:16:21 -0400144};
145
Brad Bishop4041d722017-05-21 10:06:07 -0400146/** @class ConditionalCallback
147 * @brief Callback adaptor that asssociates a condition with a callback.
148 */
Brad Bishopd1eac882018-03-29 10:34:05 -0400149template <typename CallbackAccess> class ConditionalCallback : public Callback
Brad Bishop4041d722017-05-21 10:06:07 -0400150{
Brad Bishopd1eac882018-03-29 10:34:05 -0400151 public:
152 ConditionalCallback() = delete;
153 ConditionalCallback(const ConditionalCallback&) = delete;
154 ConditionalCallback(ConditionalCallback&&) = default;
155 ConditionalCallback& operator=(const ConditionalCallback&) = delete;
156 ConditionalCallback& operator=(ConditionalCallback&&) = default;
157 virtual ~ConditionalCallback() = default;
158 ConditionalCallback(const std::vector<size_t>& graphEntry,
159 Conditional& cond) :
160 graph(graphEntry),
161 condition(cond)
162 {
163 }
Brad Bishop4041d722017-05-21 10:06:07 -0400164
Brad Bishopd1eac882018-03-29 10:34:05 -0400165 /** @brief Run the callback if the condition is satisfied. */
166 virtual void operator()(Context ctx) override
167 {
168 if (condition())
Brad Bishop4041d722017-05-21 10:06:07 -0400169 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400170 (*CallbackAccess::get()[graph[0]])(ctx);
Brad Bishop4041d722017-05-21 10:06:07 -0400171 }
Brad Bishopd1eac882018-03-29 10:34:05 -0400172 }
Brad Bishop4041d722017-05-21 10:06:07 -0400173
Brad Bishopd1eac882018-03-29 10:34:05 -0400174 protected:
175 /** @brief The index of the callback to conditionally invoke. */
176 const std::vector<size_t>& graph;
Brad Bishop4041d722017-05-21 10:06:07 -0400177
Brad Bishopd1eac882018-03-29 10:34:05 -0400178 /** @brief The condition to test. */
179 Conditional& condition;
Brad Bishop4041d722017-05-21 10:06:07 -0400180};
181
Brad Bishop3539db62017-05-30 14:21:12 -0400182/** @class DeferrableCallback
183 *
184 * Deferrable callbacks wait a configurable period before
185 * invoking their associated callback.
186 *
Gunnar Mills78199b42017-10-25 16:30:18 -0500187 * When the callback condition is initially met, start a timer. If the
Brad Bishop3539db62017-05-30 14:21:12 -0400188 * condition is tested again before the timer expires and it is not
189 * met cancel the timer. If the timer expires invoke the associated
190 * callback.
191 *
192 * @tparam CallbackAccess - Provide access to callback group instances.
193 * @tparam TimerType - Delegated timer access methods.
194 */
195template <typename CallbackAccess, typename TimerType>
196class DeferrableCallback : public ConditionalCallback<CallbackAccess>
197{
Brad Bishopd1eac882018-03-29 10:34:05 -0400198 public:
199 DeferrableCallback() = delete;
200 DeferrableCallback(const DeferrableCallback&) = delete;
201 DeferrableCallback(DeferrableCallback&&) = default;
202 DeferrableCallback& operator=(const DeferrableCallback&) = delete;
203 DeferrableCallback& operator=(DeferrableCallback&&) = default;
204 ~DeferrableCallback() = default;
Brad Bishop3539db62017-05-30 14:21:12 -0400205
Brad Bishopd1eac882018-03-29 10:34:05 -0400206 DeferrableCallback(const std::vector<size_t>& graphEntry, Conditional& cond,
207 const std::chrono::microseconds& delay) :
208 ConditionalCallback<CallbackAccess>(graphEntry, cond),
209 delayInterval(delay), timer(nullptr)
210 {
211 }
Brad Bishop3539db62017-05-30 14:21:12 -0400212
Brad Bishopd1eac882018-03-29 10:34:05 -0400213 void operator()(Context ctx) override
214 {
215 if (!timer)
Brad Bishop3539db62017-05-30 14:21:12 -0400216 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400217 timer = std::make_unique<TimerType>(
218 // **INDENT-OFF**
219 [ctx, this](auto& source) {
220 this->ConditionalCallback<CallbackAccess>::operator()(ctx);
221 });
222 // **INDENT-ON**
223 timer->disable();
Brad Bishop3539db62017-05-30 14:21:12 -0400224 }
225
Brad Bishopd1eac882018-03-29 10:34:05 -0400226 if (this->condition())
227 {
228 if (!timer->enabled())
229 {
230 // This is the first time the condition evaluated.
231 // Start the countdown.
232 timer->update(timer->now() + delayInterval);
233 timer->enable();
234 }
235 }
236 else
237 {
238 // The condition did not evaluate. Stop the countdown.
239 timer->disable();
240 }
241 }
Brad Bishop3539db62017-05-30 14:21:12 -0400242
Brad Bishopd1eac882018-03-29 10:34:05 -0400243 private:
244 /** @brief The length to wait for the condition to stop evaluating. */
245 std::chrono::microseconds delayInterval;
246
247 /** @brief Delegated timer functions. */
248 std::unique_ptr<TimerType> timer;
Brad Bishop3539db62017-05-30 14:21:12 -0400249};
250
Brad Bishopc1283ae2017-05-20 21:42:38 -0400251} // namespace monitoring
252} // namespace dbus
253} // namespace phosphor