Embedded Template Library 1.0
message_bus.h
1/******************************************************************************
2The MIT License(MIT)
3
4Embedded Template Library.
5https://github.com/ETLCPP/etl
6https://www.etlcpp.com
7
8Copyright(c) 2017 John Wellbelove
9
10Permission is hereby granted, free of charge, to any person obtaining a copy
11of this software and associated documentation files(the "Software"), to deal
12in the Software without restriction, including without limitation the rights
13to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
14copies of the Software, and to permit persons to whom the Software is
15furnished to do so, subject to the following conditions :
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26SOFTWARE.
27******************************************************************************/
28
29#ifndef ETL_MESSAGE_BUS_INCLUDED
30#define ETL_MESSAGE_BUS_INCLUDED
31
32#include "platform.h"
33#include "algorithm.h"
34#include "vector.h"
35#include "nullptr.h"
36#include "error_handler.h"
37#include "exception.h"
38#include "message_types.h"
39#include "message.h"
40#include "message_router.h"
41
42#include <stdint.h>
43
44namespace etl
45{
46 //***************************************************************************
48 //***************************************************************************
50 {
51 public:
52
53 message_bus_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
54 : etl::exception(reason_, file_name_, line_number_)
55 {
56 }
57 };
58
59 //***************************************************************************
61 //***************************************************************************
63 {
64 public:
65
66 message_bus_too_many_subscribers(string_type file_name_, numeric_type line_number_)
67 : message_bus_exception(ETL_ERROR_TEXT("message bus:too many subscribers", ETL_MESSAGE_BUS_FILE_ID"A"), file_name_, line_number_)
68 {
69 }
70 };
71
72 //***************************************************************************
74 //***************************************************************************
76 {
77 private:
78
80
81 public:
82
83 using etl::imessage_router::receive;
84
85 //*******************************************
87 //*******************************************
89 {
90 bool ok = true;
91
92 // There's no point adding routers that don't consume messages.
93 if (router.is_consumer())
94 {
95 ok = !router_list.full();
96
98
99 if (ok)
100 {
101 router_list_t::iterator irouter = etl::upper_bound(router_list.begin(),
102 router_list.end(),
103 router.get_message_router_id(),
104 compare_router_id());
105
106 router_list.insert(irouter, &router);
107 }
108 }
109
110 return ok;
111 }
112
113 //*******************************************
115 //*******************************************
116 void unsubscribe(etl::message_router_id_t id)
117 {
118 if (id == etl::imessage_bus::ALL_MESSAGE_ROUTERS)
119 {
120 clear();
121 }
122 else
123 {
124 ETL_OR_STD::pair<router_list_t::iterator, router_list_t::iterator> range = etl::equal_range(router_list.begin(),
125 router_list.end(),
126 id,
127 compare_router_id());
128
129 router_list.erase(range.first, range.second);
130 }
131 }
132
133 //*******************************************
135 {
136 router_list_t::iterator irouter = etl::find(router_list.begin(),
137 router_list.end(),
138 &router);
139
140 if (irouter != router_list.end())
141 {
142 router_list.erase(irouter);
143 }
144 }
145
146 //*******************************************
147 virtual void receive(const etl::imessage& message) ETL_OVERRIDE
148 {
149 receive(etl::imessage_router::ALL_MESSAGE_ROUTERS, message);
150 }
151
152 //*******************************************
153 virtual void receive(etl::shared_message shared_msg) ETL_OVERRIDE
154 {
155 receive(etl::imessage_router::ALL_MESSAGE_ROUTERS, shared_msg);
156 }
157
158 //*******************************************
159 virtual void receive(etl::message_router_id_t destination_router_id,
160 const etl::imessage& message) ETL_OVERRIDE
161 {
162 switch (destination_router_id)
163 {
164 //*****************************
165 // Broadcast to all routers.
166 case etl::imessage_router::ALL_MESSAGE_ROUTERS:
167 {
168 router_list_t::iterator irouter = router_list.begin();
169
170 // Broadcast to everyone.
171 while (irouter != router_list.end())
172 {
173 etl::imessage_router& router = **irouter;
174
175 if (router.accepts(message.get_message_id()))
176 {
177 router.receive(message);
178 }
179
180 ++irouter;
181 }
182
183 break;
184 }
185
186 //*****************************
187 // Must be an addressed message.
188 default:
189 {
190 router_list_t::iterator irouter = router_list.begin();
191
192 // Find routers with the id.
193 ETL_OR_STD::pair<router_list_t::iterator, router_list_t::iterator> range = etl::equal_range(router_list.begin(),
194 router_list.end(),
195 destination_router_id,
196 compare_router_id());
197
198 // Call all of them.
199 while (range.first != range.second)
200 {
201 if ((*(range.first))->accepts(message.get_message_id()))
202 {
203 (*(range.first))->receive(message);
204 }
205
206 ++range.first;
207 }
208
209 // Do any message buses.
210 // These are always at the end of the list.
211 irouter = etl::lower_bound(router_list.begin(),
212 router_list.end(),
213 etl::imessage_bus::MESSAGE_BUS,
214 compare_router_id());
215
216 while (irouter != router_list.end())
217 {
218 // So pass it on.
219 (*irouter)->receive(destination_router_id, message);
220
221 ++irouter;
222 }
223
224 break;
225 }
226 }
227
228 if (has_successor())
229 {
231
232 if (successor.accepts(message.get_message_id()))
233 {
234 successor.receive(destination_router_id, message);
235 }
236 }
237 }
238
239 //********************************************
240 virtual void receive(etl::message_router_id_t destination_router_id,
241 etl::shared_message shared_msg) ETL_OVERRIDE
242 {
243 switch (destination_router_id)
244 {
245 //*****************************
246 // Broadcast to all routers.
247 case etl::imessage_router::ALL_MESSAGE_ROUTERS:
248 {
249 router_list_t::iterator irouter = router_list.begin();
250
251 // Broadcast to everyone.
252 while (irouter != router_list.end())
253 {
254 etl::imessage_router& router = **irouter;
255
256 if (router.accepts(shared_msg.get_message().get_message_id()))
257 {
258 router.receive(shared_msg);
259 }
260
261 ++irouter;
262 }
263
264 break;
265 }
266
267 //*****************************
268 // Must be an addressed message.
269 default:
270 {
271 // Find routers with the id.
272 ETL_OR_STD::pair<router_list_t::iterator, router_list_t::iterator> range = etl::equal_range(router_list.begin(),
273 router_list.end(),
274 destination_router_id,
275 compare_router_id());
276
277 // Call all of them.
278 while (range.first != range.second)
279 {
280 if ((*(range.first))->accepts(shared_msg.get_message().get_message_id()))
281 {
282 (*(range.first))->receive(shared_msg);
283 }
284
285 ++range.first;
286 }
287
288 // Do any message buses.
289 // These are always at the end of the list.
290 router_list_t::iterator irouter = etl::lower_bound(router_list.begin(),
291 router_list.end(),
292 etl::imessage_bus::MESSAGE_BUS,
293 compare_router_id());
294
295 while (irouter != router_list.end())
296 {
297 // So pass it on.
298 (*irouter)->receive(destination_router_id, shared_msg);
299
300 ++irouter;
301 }
302
303 break;
304 }
305 }
306
307 if (has_successor())
308 {
310
311 if (successor.accepts(shared_msg.get_message().get_message_id()))
312 {
313 successor.receive(destination_router_id, shared_msg);
314 }
315 }
316 }
317
318 using imessage_router::accepts;
319
320 //*******************************************
323 //*******************************************
324 bool accepts(etl::message_id_t) const ETL_OVERRIDE
325 {
326 return true;
327 }
328
329 //*******************************************
330 size_t size() const
331 {
332 return router_list.size();
333 }
334
335 //*******************************************
336 void clear()
337 {
338 router_list.clear();
339 }
340
341 //********************************************
342 ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE
343 {
344 return false;
345 }
346
347 //********************************************
348 bool is_producer() const ETL_OVERRIDE
349 {
350 return true;
351 }
352
353 //********************************************
354 bool is_consumer() const ETL_OVERRIDE
355 {
356 return true;
357 }
358
359 protected:
360
361 //*******************************************
363 //*******************************************
365 : imessage_router(etl::imessage_router::MESSAGE_BUS),
366 router_list(list)
367 {
368 }
369
370 //*******************************************
372 //*******************************************
375 router_list(list)
376 {
377 }
378
379 private:
380
381 //*******************************************
382 // How to compare routers to router ids.
383 //*******************************************
384 struct compare_router_id
385 {
386 bool operator()(const etl::imessage_router* prouter, etl::message_router_id_t id) const
387 {
388 return prouter->get_message_router_id() < id;
389 }
390
391 bool operator()(etl::message_router_id_t id, const etl::imessage_router* prouter) const
392 {
393 return id < prouter->get_message_router_id();
394 }
395 };
396
397 router_list_t& router_list;
398 };
399
400 //***************************************************************************
402 //***************************************************************************
403 template <uint_least8_t MAX_ROUTERS_>
405 {
406 public:
407
408 //*******************************************
410 //*******************************************
412 : imessage_bus(router_list)
413 {
414 }
415
416 //*******************************************
418 //*******************************************
420 : imessage_bus(router_list, successor)
421 {
422 }
423
424 private:
425
427 };
428}
429
430#endif
Interface for message bus.
Definition: message_bus.h:76
imessage_bus(router_list_t &list, etl::imessage_router &successor)
Constructor.
Definition: message_bus.h:373
bool accepts(etl::message_id_t) const ETL_OVERRIDE
Definition: message_bus.h:324
bool subscribe(etl::imessage_router &router)
Subscribe to the bus.
Definition: message_bus.h:88
void unsubscribe(etl::message_router_id_t id)
Unsubscribe from the bus.
Definition: message_bus.h:116
imessage_bus(router_list_t &list)
Constructor.
Definition: message_bus.h:364
This is the base of all message routers.
Definition: message_router_generator.h:121
Definition: message.h:69
A templated list implementation that uses a fixed size buffer.
Definition: list.h:2030
Base exception class for message bus.
Definition: message_bus.h:50
Too many subscribers.
Definition: message_bus.h:63
The message bus.
Definition: message_bus.h:405
message_bus()
Constructor.
Definition: message_bus.h:411
message_bus(etl::imessage_router &successor)
Constructor.
Definition: message_bus.h:419
Definition: shared_message.h:49
Adds successor traits to a class.
Definition: successor.h:73
bool has_successor() const
Does this have a successor?
Definition: successor.h:184
successor_type & get_successor() const
Definition: successor.h:174
successor()
Default constructor.
Definition: successor.h:81
#define ETL_ASSERT(b, e)
Definition: error_handler.h:316
Definition: exception.h:47
iterator begin()
Definition: vector.h:100
void clear()
Clears the vector.
Definition: vector.h:414
iterator end()
Definition: vector.h:118
bool full() const
Definition: vector.h:977
size_type size() const
Definition: vector.h:959
iterator erase(iterator i_element)
Definition: vector.h:865
iterator insert(const_iterator position, const_reference value)
Definition: vector.h:560
bitset_ext
Definition: absolute.h:38
uint_least8_t message_id_t
Allow alternative type for message id.
Definition: message_types.h:40