Mbed OS Reference
Loading...
Searching...
No Matches
ChainableEventHandler.h
1/* mbed Microcontroller Library
2 * Copyright (c) 2020 ARM Limited
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#ifndef MBED_CHAINABLEEVENTHANDLER_H_
19#define MBED_CHAINABLEEVENTHANDLER_H_
20
21#include <new>
22
23/**
24 * Base class for chainable EventHandlers. Acts as a collection
25 * of discrete EventHandlers that can be linked together and
26 * notified when relevant events happen
27 */
28template<typename T>
30{
31
32public:
33
35
37 // Clean up all nodes
38 auto it = head;
39 while(it) {
40 node_t* temp = it;
41 it = it->next;
42 delete temp;
43 }
44 }
45
46 /**
47 * Add an EventHandler to be notified of events sent to
48 * this ChainableEventHandler
49 *
50 * @param[in] event_handler Handler to add to chain
51 *
52 * @retval true if adding EventHandler was successful, false otherwise
53 */
54 bool addEventHandler(T* event_handler) {
55 auto eh = new (std::nothrow) node_t { event_handler, nullptr };
56 if(!eh) { return false; }
57 if(!head) {
58 head = eh;
59 } else {
60 auto *it = head;
61 while(it->next) {
62 it = it->next;
63 }
64 it->next = eh;
65 }
66 return true;
67 }
68
69 /**
70 * Remove an EventHandler previously added with addEventHandler.
71 *
72 * @param[in] event_handler Pointer to event handler to remove
73 */
74 void removeEventHandler(T* event_handler) {
75 node_t* to_remove = head;
76 if(head->eh == event_handler) {
77 head = head->next;
78 } else {
79 auto* it = head;
80 while(it->next) {
81 if(it->next->eh == event_handler) {
82 to_remove = it->next;
83 break;
84 }
85 it = it->next;
86 }
87 if(it->next) {
88 it->next = to_remove->next;
89 } else {
90 to_remove = nullptr;
91 }
92 }
93
94 delete to_remove;
95 }
96
97 /**
98 * Test if an event handler is present in the chain or not.
99 *
100 * @param[in] event_handler Pointer to event handler to check
101 */
102 bool isEventHandlerPresent(T* event_handler) {
103 auto* it = head;
104 while (it) {
105 if (it == event_handler) {
106 return true;
107 }
108 it = it->next;
109 }
110 return false;
111 }
112
113protected:
114
115 template<typename... FnArgs, typename... Args>
116 void execute_on_all(void (T::*fn)(FnArgs...), Args&&... args) {
117 auto it = head;
118 while(it) {
119 // we do not use std::forward, args have to remain lvalues
120 // as they are passed to multiple handlers
121 (it->eh->*fn)(args...);
122 it = it->next;
123 }
124 }
125
126private:
127
128 struct node_t {
129 T* eh;
130 node_t* next = nullptr;
131 };
132
133 node_t *head = nullptr;
134
135};
136
137#endif /* MBED_CHAINABLEEVENTHANDLER_H_ */
Base class for chainable EventHandlers.
bool addEventHandler(T *event_handler)
Add an EventHandler to be notified of events sent to this ChainableEventHandler.
bool isEventHandlerPresent(T *event_handler)
Test if an event handler is present in the chain or not.
void removeEventHandler(T *event_handler)
Remove an EventHandler previously added with addEventHandler.