Control Surface main
MIDI Control Surface library for Arduino
Loading...
Searching...
No Matches
Updatable.hpp
Go to the documentation of this file.
1/* ✔ */
2
3#pragma once
4
6
7AH_DIAGNOSTIC_WERROR() // Enable errors on warnings
8
9#include <AH/Containers/CRTP.hpp>
11#include <AH/Error/Error.hpp>
12#include <AH/STL/type_traits>
13#include <AH/STL/utility> // std::forward
15#include <stddef.h>
16
18
31template <class Derived>
32class UpdatableCRTP : public DoublyLinkable<Derived> {
33
34 public:
35#if defined(__GNUC__) && !defined(__clang__)
36#pragma GCC diagnostic push
37#pragma GCC diagnostic ignored "-Wattributes"
38#endif
39
40 // When a Derived instance is constructed, the base class constructor
41 // UpdatableCRTP is called first. Because the Derived constructor hasn't
42 // been run yet, the dynamic type is just Updatable, not yet Derived.
43 // The undefined behavior sanitizer checks this dynamic type when the this
44 // pointer is casted to Derived using the CRTP macro, and thus causes an
45 // error.
46 // The constructor only casts and stores the pointer, it doesn't dereference
47 // it to call any of Derived methods, so I don't think that it's undefined
48 // behavior (and I don't know of a better way to do this).
49 // Also see https://stackoverflow.com/q/61061051/6356744
50
51 protected:
54 UpdatableCRTP() __attribute__((no_sanitize("undefined"))) {
55 updatables.append(CRTP(Derived));
56 }
57
59 __attribute__((no_sanitize("undefined")))
61 updatables.append(CRTP(Derived));
62 }
63 UpdatableCRTP &operator=(const UpdatableCRTP &) { return *this; }
64
66 updatables.append(CRTP(Derived));
67 }
68 UpdatableCRTP &operator=(UpdatableCRTP &&) { return *this; }
69
70 public:
72 virtual ~UpdatableCRTP() __attribute__((no_sanitize("undefined"))) {
73 if (updatables.couldContain(CRTP(Derived)))
74 updatables.remove(CRTP(Derived));
75 }
76
77#if defined(__GNUC__) && !defined(__clang__)
78#pragma GCC diagnostic pop
79#endif
80
81 public:
84
85 template <class... Args>
86 static void __attribute__((always_inline))
87 applyToAll(void (Derived::*method)(Args...), Args... args) {
88 for (auto &el : updatables)
89 (el.*method)(args...);
90 }
91
93
94 public:
97
100 void enable() {
101 if (isEnabled()) {
102 ERROR(F("Error: This element is already enabled."), 0x1212);
103 return; // LCOV_EXCL_LINE
104 }
105 updatables.append(CRTP(Derived));
106 }
107
110 void disable() {
111 if (!isEnabled()) {
112 ERROR(F("Error: This element is already disabled."), 0x1213);
113 return; // LCOV_EXCL_LINE
114 }
115 updatables.remove(CRTP(Derived));
116 }
117
124 bool isEnabled() const {
125 return updatables.couldContain(CRTP(const Derived));
126 }
127
129 static void enable(UpdatableCRTP *element) { element->enable(); }
131 static void enable(UpdatableCRTP &element) { element.enable(); }
133 template <class U, size_t N>
134 static void enable(U (&array)[N]) {
135 for (U &el : array)
136 enable(el);
137 }
138
140 static void disable(UpdatableCRTP *element) { element->disable(); }
142 static void disable(UpdatableCRTP &element) { element.disable(); }
144 template <class U, size_t N>
145 static void disable(U (&array)[N]) {
146 for (U &el : array)
147 disable(el);
148 }
149
151 void moveDown() { updatables.moveDown(CRTP(Derived)); }
152
154
155 protected:
157};
158
159template <class Derived>
161
163
172template <class T = NormalUpdatable>
173class Updatable : public UpdatableCRTP<Updatable<T>> {
174 public:
177
179 virtual void begin() = 0;
180
182 virtual void update() = 0;
183
186 static void beginAll() { Updatable::applyToAll(&Updatable::begin); }
187
190 static void updateAll() { Updatable::applyToAll(&Updatable::update); }
191
193};
194
196
#define END_AH_NAMESPACE
#define BEGIN_AH_NAMESPACE
#define CRTP(Derived)
Helper for the Curiously Recurring Template Pattern.
Definition CRTP.hpp:4
#define ERROR(msg, errc)
Definition Error.hpp:22
#define AH_DIAGNOSTIC_POP()
Definition Warnings.hpp:50
#define AH_DIAGNOSTIC_WERROR()
Definition Warnings.hpp:49
A class that reads and filters an analog input.
A super class for object that have to be updated regularly.
Definition Updatable.hpp:32
static void enable(UpdatableCRTP &element)
Enable this updatable: insert it into the linked list of instances, so it gets updated automatically.
UpdatableCRTP(UpdatableCRTP &&) __attribute__((no_sanitize("undefined")))
Definition Updatable.hpp:65
static void enable(U(&array)[N])
Enable this updatable: insert it into the linked list of instances, so it gets updated automatically.
UpdatableCRTP & operator=(UpdatableCRTP &&)
Definition Updatable.hpp:68
UpdatableCRTP(const UpdatableCRTP &) __attribute__((no_sanitize("undefined")))
Definition Updatable.hpp:58
UpdatableCRTP() __attribute__((no_sanitize("undefined")))
Constructor: create an Updatable and add it to the linked list of instances.
Definition Updatable.hpp:54
void moveDown()
Move down this element in the list.
void enable()
Enable this updatable: insert it into the linked list of instances, so it gets updated automatically.
static DoublyLinkedList< Derived > updatables
static void disable(UpdatableCRTP &element)
Disable this updatable: remove it from the linked list of instances, so it no longer gets updated aut...
UpdatableCRTP & operator=(const UpdatableCRTP &)
Definition Updatable.hpp:63
virtual ~UpdatableCRTP() __attribute__((no_sanitize("undefined")))
Destructor: remove the updatable from the linked list of instances.
Definition Updatable.hpp:72
void disable()
Disable this updatable: remove it from the linked list of instances, so it no longer gets updated aut...
bool isEnabled() const
Check if this updatable is enabled.
static void disable(UpdatableCRTP *element)
Disable this updatable: remove it from the linked list of instances, so it no longer gets updated aut...
static void disable(U(&array)[N])
Disable this updatable: remove it from the linked list of instances, so it no longer gets updated aut...
static void enable(UpdatableCRTP *element)
Enable this updatable: insert it into the linked list of instances, so it gets updated automatically.
A super class for object that have to be updated regularly.
static void updateAll()
Update all enabled instances of this class.
static void beginAll()
Begin all enabled instances of this class.
virtual void update()=0
Update this updatable.
virtual void begin()=0
Initialize this updatable.
A class that can be inherited from to allow inserting into a DoublyLinkedList.