| Brad Bishop | c1283ae | 2017-05-20 21:42:38 -0400 | [diff] [blame] | 1 | #pragma once | 
|  | 2 |  | 
| Brad Bishop | 3539db6 | 2017-05-30 14:21:12 -0400 | [diff] [blame] | 3 | #include <chrono> | 
| Brad Bishop | c1283ae | 2017-05-20 21:42:38 -0400 | [diff] [blame] | 4 | #include "data_types.hpp" | 
|  | 5 |  | 
|  | 6 | namespace phosphor | 
|  | 7 | { | 
|  | 8 | namespace dbus | 
|  | 9 | { | 
|  | 10 | namespace monitoring | 
|  | 11 | { | 
|  | 12 |  | 
|  | 13 | /** @class Callback | 
|  | 14 | *  @brief Callback interface. | 
|  | 15 | * | 
|  | 16 | *  Callbacks of any type can be run. | 
|  | 17 | */ | 
|  | 18 | class Callback | 
|  | 19 | { | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 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; | 
| Brad Bishop | c1283ae | 2017-05-20 21:42:38 -0400 | [diff] [blame] | 27 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 28 | /** @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 Bishop | c1283ae | 2017-05-20 21:42:38 -0400 | [diff] [blame] | 36 | }; | 
|  | 37 |  | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 38 | /** @class Conditional | 
|  | 39 | *  @brief Condition interface. | 
|  | 40 | * | 
|  | 41 | *  Conditions of any type can be tested for true or false. | 
|  | 42 | */ | 
|  | 43 | class Conditional | 
|  | 44 | { | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 45 | 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 Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 52 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 53 | /** @brief Test the condition. */ | 
|  | 54 | virtual bool operator()() = 0; | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 55 | }; | 
|  | 56 |  | 
|  | 57 | /** @class IndexedConditional | 
|  | 58 | *  @brief Condition with an index. | 
|  | 59 | */ | 
|  | 60 | class IndexedConditional : public Conditional | 
|  | 61 | { | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 62 | 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 Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 69 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 70 | explicit IndexedConditional(const PropertyIndex& conditionIndex) : | 
|  | 71 | Conditional(), index(conditionIndex) | 
|  | 72 | { | 
|  | 73 | } | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 74 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 75 | /** @brief Test the condition. */ | 
|  | 76 | virtual bool operator()() override = 0; | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 77 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 78 | protected: | 
|  | 79 | /** @brief Property names and their associated storage. */ | 
|  | 80 | const PropertyIndex& index; | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 81 | }; | 
|  | 82 |  | 
| Brad Bishop | c1283ae | 2017-05-20 21:42:38 -0400 | [diff] [blame] | 83 | /** @class IndexedCallback | 
|  | 84 | *  @brief Callback with an index. | 
|  | 85 | */ | 
|  | 86 | class IndexedCallback : public Callback | 
|  | 87 | { | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 88 | 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 Bishop | c1283ae | 2017-05-20 21:42:38 -0400 | [diff] [blame] | 99 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 100 | /** @brief Run the callback. */ | 
|  | 101 | virtual void operator()(Context ctx) override = 0; | 
| Brad Bishop | c1283ae | 2017-05-20 21:42:38 -0400 | [diff] [blame] | 102 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 103 | protected: | 
|  | 104 | /** @brief Property names and their associated storage. */ | 
|  | 105 | const PropertyIndex& index; | 
| Brad Bishop | c1283ae | 2017-05-20 21:42:38 -0400 | [diff] [blame] | 106 | }; | 
|  | 107 |  | 
| Brad Bishop | 49e6617 | 2017-05-23 19:16:21 -0400 | [diff] [blame] | 108 | /** @class GroupOfCallbacks | 
|  | 109 | *  @brief Invoke multiple callbacks. | 
|  | 110 | * | 
| Gunnar Mills | 78199b4 | 2017-10-25 16:30:18 -0500 | [diff] [blame] | 111 | *  A group of callbacks is implemented as a vector of array indices | 
| Brad Bishop | 49e6617 | 2017-05-23 19:16:21 -0400 | [diff] [blame] | 112 | *  into an external array  of callbacks.  The group function call | 
| Gunnar Mills | 78199b4 | 2017-10-25 16:30:18 -0500 | [diff] [blame] | 113 | *  operator traverses the vector of indices, invoking each | 
| Brad Bishop | 49e6617 | 2017-05-23 19:16:21 -0400 | [diff] [blame] | 114 | *  callback. | 
|  | 115 | * | 
|  | 116 | *  @tparam CallbackAccess - Access to the array of callbacks. | 
|  | 117 | */ | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 118 | template <typename CallbackAccess> class GroupOfCallbacks : public Callback | 
| Brad Bishop | 49e6617 | 2017-05-23 19:16:21 -0400 | [diff] [blame] | 119 | { | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 120 | 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 Bishop | 49e6617 | 2017-05-23 19:16:21 -0400 | [diff] [blame] | 131 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 132 | /** @brief Run the callbacks. */ | 
|  | 133 | void operator()(Context ctx) override | 
|  | 134 | { | 
|  | 135 | for (auto e : graph) | 
| Brad Bishop | 49e6617 | 2017-05-23 19:16:21 -0400 | [diff] [blame] | 136 | { | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 137 | (*CallbackAccess::get()[e])(ctx); | 
| Brad Bishop | 49e6617 | 2017-05-23 19:16:21 -0400 | [diff] [blame] | 138 | } | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 139 | } | 
| Brad Bishop | 49e6617 | 2017-05-23 19:16:21 -0400 | [diff] [blame] | 140 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 141 | private: | 
|  | 142 | /** @brief The offsets of the callbacks in the group. */ | 
|  | 143 | const std::vector<size_t>& graph; | 
| Brad Bishop | 49e6617 | 2017-05-23 19:16:21 -0400 | [diff] [blame] | 144 | }; | 
|  | 145 |  | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 146 | /** @class ConditionalCallback | 
|  | 147 | *  @brief Callback adaptor that asssociates a condition with a callback. | 
|  | 148 | */ | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 149 | template <typename CallbackAccess> class ConditionalCallback : public Callback | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 150 | { | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 151 | 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 Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 164 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 165 | /** @brief Run the callback if the condition is satisfied. */ | 
|  | 166 | virtual void operator()(Context ctx) override | 
|  | 167 | { | 
|  | 168 | if (condition()) | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 169 | { | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 170 | (*CallbackAccess::get()[graph[0]])(ctx); | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 171 | } | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 172 | } | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 173 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 174 | protected: | 
|  | 175 | /** @brief The index of the callback to conditionally invoke. */ | 
|  | 176 | const std::vector<size_t>& graph; | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 177 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 178 | /** @brief The condition to test. */ | 
|  | 179 | Conditional& condition; | 
| Brad Bishop | 4041d72 | 2017-05-21 10:06:07 -0400 | [diff] [blame] | 180 | }; | 
|  | 181 |  | 
| Brad Bishop | 3539db6 | 2017-05-30 14:21:12 -0400 | [diff] [blame] | 182 | /** @class DeferrableCallback | 
|  | 183 | * | 
|  | 184 | *  Deferrable callbacks wait a configurable period before | 
|  | 185 | *  invoking their associated callback. | 
|  | 186 | * | 
| Gunnar Mills | 78199b4 | 2017-10-25 16:30:18 -0500 | [diff] [blame] | 187 | *  When the callback condition is initially met, start a timer.  If the | 
| Brad Bishop | 3539db6 | 2017-05-30 14:21:12 -0400 | [diff] [blame] | 188 | *  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 | */ | 
|  | 195 | template <typename CallbackAccess, typename TimerType> | 
|  | 196 | class DeferrableCallback : public ConditionalCallback<CallbackAccess> | 
|  | 197 | { | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 198 | 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 Bishop | 3539db6 | 2017-05-30 14:21:12 -0400 | [diff] [blame] | 205 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 206 | 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 Bishop | 3539db6 | 2017-05-30 14:21:12 -0400 | [diff] [blame] | 212 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 213 | void operator()(Context ctx) override | 
|  | 214 | { | 
|  | 215 | if (!timer) | 
| Brad Bishop | 3539db6 | 2017-05-30 14:21:12 -0400 | [diff] [blame] | 216 | { | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 217 | 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 Bishop | 3539db6 | 2017-05-30 14:21:12 -0400 | [diff] [blame] | 224 | } | 
|  | 225 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 226 | 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 Bishop | 3539db6 | 2017-05-30 14:21:12 -0400 | [diff] [blame] | 242 |  | 
| Brad Bishop | d1eac88 | 2018-03-29 10:34:05 -0400 | [diff] [blame] | 243 | 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 Bishop | 3539db6 | 2017-05-30 14:21:12 -0400 | [diff] [blame] | 249 | }; | 
|  | 250 |  | 
| Brad Bishop | c1283ae | 2017-05-20 21:42:38 -0400 | [diff] [blame] | 251 | } // namespace monitoring | 
|  | 252 | } // namespace dbus | 
|  | 253 | } // namespace phosphor |