xref: /openbmc/telemetry/src/state.hpp (revision 3a1c297a)
1 #pragma once
2 
3 #include <bitset>
4 
5 enum class ReportFlags
6 {
7     enabled,
8     valid
9 };
10 
11 enum class StateEvent
12 {
13     active,
14     inactive,
15     activated,
16     deactivated
17 };
18 
19 template <class T>
20 concept boolean = std::is_same_v<T, bool>;
21 
22 template <class Flags, class Object, Flags... Keys>
23 class State
24 {
25   public:
State(Object & object)26     explicit State(Object& object) : object(object) {}
27 
28     template <Flags... Indexes>
set(boolean auto...values)29     StateEvent set(boolean auto... values)
30     {
31         static_assert(sizeof...(Indexes) == sizeof...(values));
32 
33         const bool previous = flags.all();
34 
35         (flags.set(indexOf<0, Indexes, Keys...>(), values), ...);
36 
37         if (previous != flags.all())
38         {
39             if (flags.all())
40             {
41                 object.activate();
42                 return StateEvent::activated;
43             }
44             else
45             {
46                 object.deactivate();
47                 return StateEvent::deactivated;
48             }
49         }
50 
51         return flags.all() ? StateEvent::active : StateEvent::inactive;
52     }
53 
54     template <Flags Index>
get() const55     bool get() const
56     {
57         return flags.test(indexOf<0, Index, Keys...>());
58     }
59 
isActive() const60     bool isActive() const
61     {
62         return flags.all();
63     }
64 
65   private:
66     template <size_t Index, Flags flag, Flags it, Flags... list>
indexOf()67     static constexpr size_t indexOf()
68     {
69         if constexpr (flag == it)
70         {
71             return Index;
72         }
73         else
74         {
75             return indexOf<Index + 1, flag, list...>();
76         }
77     }
78 
79     Object& object;
80     std::bitset<sizeof...(Keys)> flags{0};
81 };
82