Initial changes

This commit is contained in:
John Wellbelove 2026-09-20 17:49:48 +01:00
parent 22bdef2ee4
commit 714409be19
10 changed files with 1229 additions and 1027 deletions

View File

@ -9,10 +9,17 @@ weight: 6
Message Broker
A variant of the observer pattern in that message routers and derived types are be able to subscribe to selected sets of messages. The message_broker is similar to the message_bus, but it provides more control over the routing of messages. While the message_bus simply broadcasts every message to all subscribers, the message_broker allows you to specify which subscribers should receive each message.
A variant of the observer pattern in that message routers and derived types are be able to subscribe to selected sets of messages. The `message_broker` is similar to the `message_bus`, but it provides more control over the routing of messages. While `message_bus` simply broadcasts every message to all subscribers, `message_broker` allows you to specify which subscribers should receive each message.
Derived from `imessage_router`.
```mermaid
classDiagram
direction TB
class message_processor
class message_broker
message_processor <|-- message_broker
```
## Types
```cpp

View File

@ -12,30 +12,39 @@ Message Bus
This page documents version `20.0.0` and above.
A variant of the observer pattern in that message routers and derived types are be able to subscribe to messages on a bus. The messages can be either broadcast, to be automatically picked up by any router that has a handler, or addressed to a particular router or router id. Message buses may be nested by setting a successor.
A variant of the observer pattern in that message routers and derived types are be able to subscribe to messages on a bus. The messages can be either broadcast, to be automatically picked up by any router that has a handler, or addressed to a particular router or router id. Message buses may be chained by setting a successor.
## imessage_bus
Derived from imessage_router.
```mermaid
classDiagram
direction TB
class message_processor
class message_bus
message_processor <|-- message_bus
```
## imessage_bus
The base for all message buses.
Inherits publicly from `etl::imessage_router`.
Inherits publicly from `etl::message_processor`.
Message buses are therefore also a type of router.
Objects of type `etl::imessage_bus` cannot be directly constructed.
## Member functions
```cpp
bool subscribe(etl::imessage_router& router)
bool subscribe(etl::message_processor& router)
```
Subscribes an `etl::imessage_router` derived class to the bus.
Subscribes an `etl::message_processor` derived class to the bus.
Returns `true` on success.
---
```cpp
void unsubscribe(etl::imessage_router& router)
void unsubscribe(etl::message_processor& router)
```
Unsubscribes the specified `etl::imessage_router` derived class from the bus.
Unsubscribes the specified `etl::message_processor` derived class from the bus.
Does not unsubscribe from nested buses.
---
@ -100,7 +109,7 @@ void clear()
```
Clears the bus of all subscribers.
Message buses inherit all of the public functions of `etl::imessage_router`.
Message buses inherit all of the public functions of `etl::message_processor`.
## Errors
@ -134,7 +143,7 @@ Constructs a message bus.
Message buses always have a router id of `etl::imessage::MESSAGE_BUS`.
```cpp
message_bus(etl::imessage_router& successor)
message_bus(etl::message_processor& successor)
```
Constructs a message bus and sets the successor.
Message buses always have a router id of `etl::imessage::MESSAGE_BUS`.

View File

@ -5,25 +5,57 @@ weight: 3
A class that will automatically route incoming messages to specific handlers based on the message types declared in the template parameter list. Messages are passed to the receive member function which will static cast it to its real type and call the matching `on_receive` function in the derived class. A compilation error will occur if the matching `on_receive` does not exist.
The `on_receive` functions are not virtual. The template base class uses `CRTP` to directly call the derived class's functions.
The `on_receive` functions are not virtual. The template base class uses [CRTP](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) to directly call the derived class's functions.
**Defines the following classes**
```cpp
etl::imessage_router
etl::message_router
etl::null_message_router
```
Note: This C++03 portion of this header is a generated from `message_router_generator.h`. To handle more than the standard 16 message types then a new one must be generated.
See [Generators](./generators-tutorial)
**Defines the following classes**
```cpp
etl::message_processor
etl::message_router
etl::null_message_router
etl::message_producer
etl::message_router_from_type_list
etl::message_router_from_type_list_t
```
## Class diagram
```mermaid
classDiagram
class successor~TDerived~
class message_processor_tag {
All_Message_Processors
Null_Message_Router
Message_Bus
Message_Broker
Message_Router
Max_Message_Router
}
class message_processor
class message_router~TDerived, TMessageTypes...~
class null_message_router
class message_producer
successor <|-- message_processor
message_processor_tag <|-- message_processor
message_processor <|-- message_router
message_router <|-- null_message_router
message_router <|-- message_producer
```
## Message router ID
Allowable router IDs run from `0` to `MAX_MESSAGE_ROUTER` (`249`) inclusive.
Allowable router IDs run from `0` to `Max_Message_Router` (`249`) inclusive.
Each message router is given an ID. Whether this ID is unique or not depends on how you are using and identifying message routers.
Note: A message router 'group' is deemed to be a set of routers with identical IDs.
The default router id is `etl::imessage_router::MESSAGE_ROUTER`.
Note: A message router *group* is deemed to be a set of routers with identical IDs.
The default router id is `etl::message_processor::Message_Router`.
### Scenario 1
- You never send a message to a router using it's ID.
@ -48,12 +80,12 @@ Router IDs will be assigned in groups. i.e. Some routers may share IDs.
All router IDs are unique
## imessage_router
## message_processor
The base class for all routers.
#### Member functions
```cpp
virtual ~imessage_router() {}
virtual ~message_processor() {}
```
---
@ -137,7 +169,7 @@ Returns `true` if the router is a consumer of messages, otherwise `false`.
---
```cpp
void set_successor(etl::imessage_router& successor);
void set_successor(etl::message_processor& successor);
```
Sets the successor router. Any unhandled message will be sent here.
Allows the router to implement the Chain Of Responsibility design pattern.
@ -147,14 +179,14 @@ Allows the router to implement the Chain Of Responsibility design pattern.
NULL_MESSAGE_ROUTER
MESSAGE_BUS
ALL_MESSAGE_ROUTERS
MAX_MESSAGE_ROUTER
Max_Message_Router
```
---
## message_router
User defined message routers are derived from this class.
Derived from `imessage_router`.
Derived from `message_processor`.
---
@ -223,15 +255,15 @@ See [etl::message_packet](./message-packet)
message_router()
```
Constructs the router.
The router id is set to `etl::imassage_router::MESSAGE_ROUTER`.
The router id is set to `etl::imassage_router::Message_Router`.
---
```cpp
message_router(etl::imessage_router& successor)
message_router(etl::message_processor& successor)
```
Constructs the router.
The router id must be between `0` and `MAX_MESSAGE_ROUTER` (`249`). Other IDs are reserved for ETL use.
The router id must be between `0` and `Max_Message_Router` (`249`). Other IDs are reserved for ETL use.
Emits an error if the id is outside the legal range.
Routers may have duplicate ids.
Sets the successor router to this one. Any unhandled message will be sent here.
@ -249,10 +281,10 @@ Routers may have duplicate ids.
---
```cpp
message_router(etl::message_router_id_t id, etl::imessage_router& successor)
message_router(etl::message_router_id_t id, etl::message_processor& successor)
```
Constructs the router.
The router id must be between 0 and MAX_MESSAGE_ROUTER (249) . Other IDs are reserved for ETL use.
The router id must be between 0 and Max_Message_Router (249) . Other IDs are reserved for ETL use.
Sets the successor router to this one. Any unhandled message will be sent here.
---
@ -301,7 +333,7 @@ Derived from `etl::message_router_exception`.
### null_message_router
This router can be used as a sink for messages or a 'null source' router.
Derived from `etl::imessage_router`.
Derived from `etl::message_processor`.
---
@ -309,7 +341,7 @@ Derived from `etl::imessage_router`.
null_message_router()
```
Constructs a null message router.
The router id will be `etl::imessage_router::NULL_MESSAGE_ROUTER`.
The router id will be `etl::message_processor::NULL_MESSAGE_ROUTER`.
---
@ -336,7 +368,7 @@ Returns an instance of `etl::null_message_router`.
## message_producer
This router can be used as a producer-only of messages, such an interrupt routine.
Derived from `etl::imessage_router`.
Derived from `etl::message_processor`.
---
@ -376,7 +408,7 @@ Returns an instance of `etl::null_message_router`.
## Global functions
```cpp
void send_message(etl::imessage_router& router,
void send_message(etl::message_processor& router,
const etl::imessage& message)
```
Send the message to the router.
@ -384,7 +416,7 @@ Send the message to the router.
---
```cpp
void send_message(etl::imessage_router& router,
void send_message(etl::message_processor& router,
etl::message_router_id_t id,
const etl::imessage& message)
```
@ -393,7 +425,7 @@ Send the message to the router if it has the specified id.
---
```cpp
void send_message(etl::imessage_router& router,
void send_message(etl::message_processor& router,
etl::shared_message& message)
```
Send the shared message to the router.
@ -401,7 +433,7 @@ Send the shared message to the router.
---
```cpp
void send_message(etl::imessage_router& router,
void send_message(etl::message_processor& router,
etl::message_router_id_t id,
etl::shared_message& message)
```
@ -451,7 +483,7 @@ public:
}
// Received a start message.
void on_receive(etl::imessage_router& sender, const Start& msg)
void on_receive(const Start& msg)
{
std::cout << "Start message received\n";
}
@ -459,7 +491,7 @@ public:
// Received a stop message.
void on_receive(const Stop& msg)
{
std::cout << "Start message received\n";
std::cout << "Stop message received\n";
}
// Received a set speed message.

View File

@ -31,7 +31,7 @@ SOFTWARE.
#include "platform.h"
#include "message.h"
#include "message_router.h"
#include "message_processor.h"
#include "message_types.h"
#include "nullptr.h"
#include "span.h"
@ -41,7 +41,7 @@ namespace etl
//***************************************************************************
/// Message broker
//***************************************************************************
class message_broker : public etl::imessage_router
class message_broker : public etl::message_processor
{
private:
@ -101,7 +101,7 @@ namespace etl
friend class message_broker;
//*******************************
subscription(etl::imessage_router& router_)
subscription(etl::message_processor& router_)
: p_router(&router_)
{
}
@ -112,7 +112,7 @@ namespace etl
virtual message_id_span_t message_id_list() const = 0;
//*******************************
etl::imessage_router* get_router() const
etl::message_processor* get_router() const
{
return p_router;
}
@ -123,16 +123,16 @@ namespace etl
return static_cast<subscription*>(get_next());
}
etl::imessage_router* const p_router;
etl::message_processor* const p_router;
};
using etl::imessage_router::receive;
using etl::message_processor::receive;
//*******************************************
/// Constructor.
//*******************************************
message_broker()
: imessage_router(etl::imessage_router::MESSAGE_BROKER)
: message_processor(etl::message_processor::MESSAGE_BROKER)
, head()
{
}
@ -140,8 +140,8 @@ namespace etl
//*******************************************
/// Constructor.
//*******************************************
message_broker(etl::imessage_router& successor_)
: imessage_router(etl::imessage_router::MESSAGE_BROKER, successor_)
message_broker(etl::message_processor& successor_)
: message_processor(etl::message_processor::MESSAGE_BROKER, successor_)
, head()
{
}
@ -150,21 +150,21 @@ namespace etl
/// Constructor.
//*******************************************
message_broker(etl::message_router_id_t id_)
: imessage_router(id_)
: message_processor(id_)
, head()
{
ETL_ASSERT((id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER) || (id_ == etl::imessage_router::MESSAGE_BROKER),
ETL_ASSERT((id_ <= etl::message_processor::MAX_MESSAGE_ROUTER) || (id_ == etl::message_processor::MESSAGE_BROKER),
ETL_ERROR(etl::message_router_illegal_id));
}
//*******************************************
/// Constructor.
//*******************************************
message_broker(etl::message_router_id_t id_, etl::imessage_router& successor_)
: imessage_router(id_, successor_)
message_broker(etl::message_router_id_t id_, etl::message_processor& successor_)
: message_processor(id_, successor_)
, head()
{
ETL_ASSERT((id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER) || (id_ == etl::imessage_router::MESSAGE_BROKER),
ETL_ASSERT((id_ <= etl::message_processor::MAX_MESSAGE_ROUTER) || (id_ == etl::message_processor::MESSAGE_BROKER),
ETL_ERROR(etl::message_router_illegal_id));
}
@ -177,7 +177,7 @@ namespace etl
}
//*******************************************
void unsubscribe(etl::imessage_router& router)
void unsubscribe(etl::message_processor& router)
{
initialise_insertion_point(&router, ETL_NULLPTR);
}
@ -185,16 +185,16 @@ namespace etl
//*******************************************
virtual void receive(const etl::imessage& msg) ETL_OVERRIDE
{
receive(etl::imessage_router::ALL_MESSAGE_ROUTERS, msg);
receive(etl::message_processor::ALL_MESSAGE_ROUTERS, msg);
}
virtual void receive(etl::shared_message shared_msg) ETL_OVERRIDE
{
receive(etl::imessage_router::ALL_MESSAGE_ROUTERS, shared_msg);
receive(etl::message_processor::ALL_MESSAGE_ROUTERS, shared_msg);
}
//*******************************************
virtual void receive(etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE
virtual void receive(etl::message_router_id_t destination_processor_id, const etl::imessage& msg) ETL_OVERRIDE
{
const etl::message_id_t id = msg.get_message_id();
@ -211,9 +211,9 @@ namespace etl
if (itr != message_ids.end())
{
etl::imessage_router* router = sub->get_router();
etl::message_processor* router = sub->get_router();
if (destination_router_id == etl::imessage_router::ALL_MESSAGE_ROUTERS || destination_router_id == router->get_message_router_id())
if (destination_processor_id == etl::message_processor::ALL_MESSAGE_ROUTERS || destination_processor_id == router->get_message_processor_id())
{
router->receive(msg);
}
@ -226,12 +226,12 @@ namespace etl
// Always pass the message on to the successor.
if (has_successor())
{
get_successor().receive(destination_router_id, msg);
get_successor().receive(destination_processor_id, msg);
}
}
//*******************************************
virtual void receive(etl::message_router_id_t destination_router_id, etl::shared_message shared_msg) ETL_OVERRIDE
virtual void receive(etl::message_router_id_t destination_processor_id, etl::shared_message shared_msg) ETL_OVERRIDE
{
const etl::message_id_t id = shared_msg.get_message().get_message_id();
@ -248,9 +248,9 @@ namespace etl
if (itr != message_ids.end())
{
etl::imessage_router* router = sub->get_router();
etl::message_processor* router = sub->get_router();
if (destination_router_id == etl::imessage_router::ALL_MESSAGE_ROUTERS || destination_router_id == router->get_message_router_id())
if (destination_processor_id == etl::message_processor::ALL_MESSAGE_ROUTERS || destination_processor_id == router->get_message_processor_id())
{
router->receive(shared_msg);
}
@ -263,11 +263,11 @@ namespace etl
// Always pass the message on to a successor.
if (has_successor())
{
get_successor().receive(destination_router_id, shared_msg);
get_successor().receive(destination_processor_id, shared_msg);
}
}
using imessage_router::accepts;
using message_processor::accepts;
//*******************************************
/// Message brokers accept messages determined
@ -288,7 +288,7 @@ namespace etl
if (itr != message_ids.end())
{
etl::imessage_router* router = sub->get_router();
etl::message_processor* router = sub->get_router();
if (router->accepts(id))
{
@ -348,9 +348,9 @@ namespace etl
private:
//*******************************************
void initialise_insertion_point(const etl::imessage_router* p_router, etl::message_broker::subscription* p_new_sub)
void initialise_insertion_point(const etl::message_processor* p_router, etl::message_broker::subscription* p_new_sub)
{
const etl::imessage_router* p_target_router = p_router;
const etl::message_processor* p_target_router = p_router;
subscription_node* p_sub = head.get_next();
subscription_node* p_sub_previous = &head;

View File

@ -34,7 +34,7 @@ SOFTWARE.
#include "error_handler.h"
#include "exception.h"
#include "message.h"
#include "message_router.h"
#include "message_processor.h"
#include "message_types.h"
#include "vector.h"
@ -73,36 +73,36 @@ namespace etl
//***************************************************************************
/// Interface for message bus
//***************************************************************************
class imessage_bus : public etl::imessage_router
class imessage_bus : public etl::message_processor
{
private:
typedef etl::ivector<etl::imessage_router*> router_list_t;
typedef etl::ivector<etl::message_processor*> processor_list_t;
public:
using etl::imessage_router::receive;
using etl::message_processor::receive;
//*******************************************
/// Subscribe to the bus.
//*******************************************
bool subscribe(etl::imessage_router& router)
bool subscribe(etl::message_processor& processor)
{
bool ok = true;
// There's no point adding routers that don't consume messages.
if (router.is_consumer())
// There's no point adding processors that don't consume messages.
if (processor.is_consumer())
{
ok = !router_list.full();
ok = !processor_list.full();
ETL_ASSERT(ok, ETL_ERROR(etl::message_bus_too_many_subscribers));
if (ok)
{
router_list_t::iterator irouter =
etl::upper_bound(router_list.begin(), router_list.end(), router.get_message_router_id(), compare_router_id());
processor_list_t::iterator iprocessor =
etl::upper_bound(processor_list.begin(), processor_list.end(), processor.get_message_processor_id(), compare_processor_id());
router_list.insert(irouter, &router);
processor_list.insert(iprocessor, &processor);
}
}
@ -112,7 +112,7 @@ namespace etl
//*******************************************
/// Unsubscribe from the bus.
//*******************************************
void unsubscribe(etl::message_router_id_t id)
void unsubscribe(etl::message_processor_id_t id)
{
if (id == etl::imessage_bus::ALL_MESSAGE_ROUTERS)
{
@ -120,58 +120,58 @@ namespace etl
}
else
{
ETL_OR_STD::pair<router_list_t::iterator, router_list_t::iterator> range =
etl::equal_range(router_list.begin(), router_list.end(), id, compare_router_id());
ETL_OR_STD::pair<processor_list_t::iterator, processor_list_t::iterator> range =
etl::equal_range(processor_list.begin(), processor_list.end(), id, compare_processor_id());
router_list.erase(range.first, range.second);
processor_list.erase(range.first, range.second);
}
}
//*******************************************
void unsubscribe(etl::imessage_router& router)
void unsubscribe(etl::message_processor& processor)
{
router_list_t::iterator irouter = etl::find(router_list.begin(), router_list.end(), &router);
processor_list_t::iterator iprocessor = etl::find(processor_list.begin(), processor_list.end(), &processor);
if (irouter != router_list.end())
if (iprocessor != processor_list.end())
{
router_list.erase(irouter);
processor_list.erase(iprocessor);
}
}
//*******************************************
virtual void receive(const etl::imessage& message) ETL_OVERRIDE
{
receive(etl::imessage_router::ALL_MESSAGE_ROUTERS, message);
receive(etl::message_processor::ALL_MESSAGE_ROUTERS, message);
}
//*******************************************
virtual void receive(etl::shared_message shared_msg) ETL_OVERRIDE
{
receive(etl::imessage_router::ALL_MESSAGE_ROUTERS, shared_msg);
receive(etl::message_processor::ALL_MESSAGE_ROUTERS, shared_msg);
}
//*******************************************
virtual void receive(etl::message_router_id_t destination_router_id, const etl::imessage& message) ETL_OVERRIDE
virtual void receive(etl::message_processor_id_t destination_processor_id, const etl::imessage& message) ETL_OVERRIDE
{
switch (destination_router_id)
switch (destination_processor_id)
{
//*****************************
// Broadcast to all routers.
case etl::imessage_router::ALL_MESSAGE_ROUTERS:
// Broadcast to all processors.
case etl::message_processor::ALL_MESSAGE_ROUTERS:
{
router_list_t::iterator irouter = router_list.begin();
processor_list_t::iterator iprocessor = processor_list.begin();
// Broadcast to everyone.
while (irouter != router_list.end())
while (iprocessor != processor_list.end())
{
etl::imessage_router& router = **irouter;
etl::message_processor& processor = **iprocessor;
if (router.accepts(message.get_message_id()))
if (processor.accepts(message.get_message_id()))
{
router.receive(message);
processor.receive(message);
}
++irouter;
++iprocessor;
}
break;
@ -181,11 +181,11 @@ namespace etl
// Must be an addressed message.
default:
{
router_list_t::iterator irouter = router_list.begin();
processor_list_t::iterator iprocessor = processor_list.begin();
// Find routers with the id.
ETL_OR_STD::pair<router_list_t::iterator, router_list_t::iterator> range =
etl::equal_range(router_list.begin(), router_list.end(), destination_router_id, compare_router_id());
// Find processors with the id.
ETL_OR_STD::pair<processor_list_t::iterator, processor_list_t::iterator> range =
etl::equal_range(processor_list.begin(), processor_list.end(), destination_processor_id, compare_processor_id());
// Call all of them.
while (range.first != range.second)
@ -200,14 +200,14 @@ namespace etl
// Do any message buses.
// These are always at the end of the list.
irouter = etl::lower_bound(router_list.begin(), router_list.end(), etl::imessage_bus::MESSAGE_BUS, compare_router_id());
iprocessor = etl::lower_bound(processor_list.begin(), processor_list.end(), etl::imessage_bus::MESSAGE_BUS, compare_processor_id());
while (irouter != router_list.end())
while (iprocessor != processor_list.end())
{
// So pass it on.
(*irouter)->receive(destination_router_id, message);
(*iprocessor)->receive(destination_processor_id, message);
++irouter;
++iprocessor;
}
break;
@ -218,33 +218,33 @@ namespace etl
{
if (get_successor().accepts(message.get_message_id()))
{
get_successor().receive(destination_router_id, message);
get_successor().receive(destination_processor_id, message);
}
}
}
//********************************************
virtual void receive(etl::message_router_id_t destination_router_id, etl::shared_message shared_msg) ETL_OVERRIDE
virtual void receive(etl::message_processor_id_t destination_processor_id, etl::shared_message shared_msg) ETL_OVERRIDE
{
switch (destination_router_id)
switch (destination_processor_id)
{
//*****************************
// Broadcast to all routers.
case etl::imessage_router::ALL_MESSAGE_ROUTERS:
// Broadcast to all processors.
case etl::message_processor::ALL_MESSAGE_ROUTERS:
{
router_list_t::iterator irouter = router_list.begin();
processor_list_t::iterator iprocessor = processor_list.begin();
// Broadcast to everyone.
while (irouter != router_list.end())
while (iprocessor != processor_list.end())
{
etl::imessage_router& router = **irouter;
etl::message_processor& processor = **iprocessor;
if (router.accepts(shared_msg.get_message().get_message_id()))
if (processor.accepts(shared_msg.get_message().get_message_id()))
{
router.receive(shared_msg);
processor.receive(shared_msg);
}
++irouter;
++iprocessor;
}
break;
@ -254,9 +254,9 @@ namespace etl
// Must be an addressed message.
default:
{
// Find routers with the id.
ETL_OR_STD::pair<router_list_t::iterator, router_list_t::iterator> range =
etl::equal_range(router_list.begin(), router_list.end(), destination_router_id, compare_router_id());
// Find processors with the id.
ETL_OR_STD::pair<processor_list_t::iterator, processor_list_t::iterator> range =
etl::equal_range(processor_list.begin(), processor_list.end(), destination_processor_id, compare_processor_id());
// Call all of them.
while (range.first != range.second)
@ -271,15 +271,15 @@ namespace etl
// Do any message buses.
// These are always at the end of the list.
router_list_t::iterator irouter =
etl::lower_bound(router_list.begin(), router_list.end(), etl::imessage_bus::MESSAGE_BUS, compare_router_id());
processor_list_t::iterator iprocessor =
etl::lower_bound(processor_list.begin(), processor_list.end(), etl::imessage_bus::MESSAGE_BUS, compare_processor_id());
while (irouter != router_list.end())
while (iprocessor != processor_list.end())
{
// So pass it on.
(*irouter)->receive(destination_router_id, shared_msg);
(*iprocessor)->receive(destination_processor_id, shared_msg);
++irouter;
++iprocessor;
}
break;
@ -290,32 +290,32 @@ namespace etl
{
if (get_successor().accepts(shared_msg.get_message().get_message_id()))
{
get_successor().receive(destination_router_id, shared_msg);
get_successor().receive(destination_processor_id, shared_msg);
}
}
}
using imessage_router::accepts;
using message_processor::accepts;
//*******************************************
/// Does this message bus accept the message id?
/// Returns <b>true</b> on the first router that does.
/// Returns <b>true</b> on the first processor that does.
//*******************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
// Check the list of subscribed routers.
router_list_t::iterator irouter = router_list.begin();
// Check the list of subscribed processors.
processor_list_t::iterator iprocessor = processor_list.begin();
while (irouter != router_list.end())
while (iprocessor != processor_list.end())
{
etl::imessage_router& router = **irouter;
etl::message_processor& processor = **iprocessor;
if (router.accepts(id))
if (processor.accepts(id))
{
return true;
}
++irouter;
++iprocessor;
}
// Check any successor.
@ -333,13 +333,13 @@ namespace etl
//*******************************************
size_t size() const
{
return router_list.size();
return processor_list.size();
}
//*******************************************
void clear()
{
router_list.clear();
processor_list.clear();
}
//********************************************
@ -366,40 +366,40 @@ namespace etl
//*******************************************
/// Constructor.
//*******************************************
imessage_bus(router_list_t& list)
: imessage_router(etl::imessage_router::MESSAGE_BUS)
, router_list(list)
imessage_bus(processor_list_t& list)
: message_processor(etl::message_processor::MESSAGE_BUS)
, processor_list(list)
{
}
//*******************************************
/// Constructor.
//*******************************************
imessage_bus(router_list_t& router_list_, etl::imessage_router& successor_)
: imessage_router(etl::imessage_router::MESSAGE_BUS, successor_)
, router_list(router_list_)
imessage_bus(processor_list_t& processor_list_, etl::message_processor& successor_)
: message_processor(etl::message_processor::MESSAGE_BUS, successor_)
, processor_list(processor_list_)
{
}
private:
//*******************************************
// How to compare routers to router ids.
// How to compare processors to processor ids.
//*******************************************
struct compare_router_id
struct compare_processor_id
{
bool operator()(const etl::imessage_router* prouter, etl::message_router_id_t id) const
bool operator()(const etl::message_processor* pprocessor, etl::message_processor_id_t id) const
{
return prouter->get_message_router_id() < id;
return pprocessor->get_message_processor_id() < id;
}
bool operator()(etl::message_router_id_t id, const etl::imessage_router* prouter) const
bool operator()(etl::message_processor_id_t id, const etl::message_processor* pprocessor) const
{
return id < prouter->get_message_router_id();
return id < pprocessor->get_message_processor_id();
}
};
router_list_t& router_list;
processor_list_t& processor_list;
};
//***************************************************************************
@ -414,21 +414,21 @@ namespace etl
/// Constructor.
//*******************************************
message_bus()
: imessage_bus(router_list)
: imessage_bus(processor_list)
{
}
//*******************************************
/// Constructor.
//*******************************************
message_bus(etl::imessage_router& successor_)
: imessage_bus(router_list, successor_)
message_bus(etl::message_processor& successor_)
: imessage_bus(processor_list, successor_)
{
}
private:
etl::vector<etl::imessage_router*, MAX_ROUTERS_> router_list;
etl::vector<etl::message_processor*, MAX_ROUTERS_> processor_list;
};
} // namespace etl

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@ Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2017 John Wellbelove
Copyright(c) 2026 John Wellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
@ -29,872 +29,8 @@ SOFTWARE.
#ifndef ETL_MESSAGE_ROUTER_INCLUDED
#define ETL_MESSAGE_ROUTER_INCLUDED
#include "platform.h"
#include "alignment.h"
#include "array.h"
#include "error_handler.h"
#include "exception.h"
#include "largest.h"
#include "message.h"
#include "message_packet.h"
#include "message_types.h"
#include "shared_message.h"
#include "successor.h"
#include "type_list.h"
#include "type_traits.h"
#include <stddef.h>
namespace etl
{
//***************************************************************************
/// Base exception class for message router
//***************************************************************************
class message_router_exception : public etl::exception
{
public:
message_router_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
: etl::exception(reason_, file_name_, line_number_)
{
}
};
//***************************************************************************
/// Router id is out of the legal range.
//***************************************************************************
class message_router_illegal_id : public etl::message_router_exception
{
public:
message_router_illegal_id(string_type file_name_, numeric_type line_number_)
: message_router_exception(ETL_ERROR_TEXT("message router:illegal id", ETL_MESSAGE_ROUTER_FILE_ID"A"), file_name_, line_number_)
{
}
};
namespace private_message_router
{
#if ETL_USING_CPP11
//***************************************************************************
// Traits for a message router.
// message packet type
// message type_list
// sorted message type_list.
//***************************************************************************
template <typename... TMessageTypes>
class traits
{
private:
using message_id_sequence = etl::index_sequence<TMessageTypes::ID...>;
public:
using message_packet = etl::message_packet<TMessageTypes...>;
using message_types = etl::type_list<TMessageTypes...>;
using sorted_message_types = etl::type_list_sort_t<message_types, etl::compare_message_id_less>;
static_assert(etl::type_list_is_unique<message_types>::value, "All TMessageTypes must be unique");
static_assert(etl::type_list_all_of<message_types, etl::is_message_type>::value,
"All TMessageTypes must satisfy the condition etl::is_message_type");
static_assert(etl::index_sequence_is_unique<message_id_sequence>::value, "All message IDs must be unique");
};
//***************************************************************************
// Specialisation of traits for no message types.
// message packet type
// message type_list
// sorted message type_list.
//***************************************************************************
template <>
class traits<>
{
public:
using message_packet = etl::message_packet<>;
using message_types = etl::type_list<>;
using sorted_message_types = etl::type_list<>;
};
#else
//***************************************************************************
// C++03 empty traits placeholder.
//***************************************************************************
template <typename T1 = void>
class traits
{
};
#endif
} // namespace private_message_router
//***************************************************************************
/// Forward declare null message router functionality.
//***************************************************************************
class imessage_router;
etl::imessage_router& get_null_message_router();
//***************************************************************************
/// This is the base of all message routers.
//***************************************************************************
class imessage_router : public etl::successor<imessage_router>
{
public:
virtual ~imessage_router() {}
virtual void receive(const etl::imessage&) = 0;
virtual bool accepts(etl::message_id_t) const = 0;
virtual bool is_null_router() const = 0;
virtual bool is_producer() const = 0;
virtual bool is_consumer() const = 0;
//********************************************
virtual void receive(etl::message_router_id_t destination_router_id, const etl::imessage& message)
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(message);
}
}
//********************************************
virtual void receive(etl::shared_message shared_msg)
{
receive(shared_msg.get_message());
}
//********************************************
virtual void receive(etl::message_router_id_t destination_router_id, etl::shared_message shared_msg)
{
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
{
receive(shared_msg);
}
}
//********************************************
bool accepts(const etl::imessage& msg) const
{
return accepts(msg.get_message_id());
}
//********************************************
etl::message_router_id_t get_message_router_id() const
{
return message_router_id;
}
enum
{
NULL_MESSAGE_ROUTER = 255,
MESSAGE_BUS = 254,
ALL_MESSAGE_ROUTERS = 253,
MESSAGE_BROKER = 252,
MESSAGE_ROUTER = 251,
MAX_MESSAGE_ROUTER = 249
};
protected:
imessage_router(etl::message_router_id_t id_)
: message_router_id(id_)
{
}
imessage_router(etl::message_router_id_t id_, imessage_router& successor_)
: successor(successor_)
, message_router_id(id_)
{
}
private:
// Disabled.
imessage_router(const imessage_router&);
imessage_router& operator=(const imessage_router&);
etl::message_router_id_t message_router_id;
};
//***************************************************************************
/// This router can be used as a sink for messages or a 'null source' router.
//***************************************************************************
class null_message_router
: public imessage_router
, public private_message_router::traits<>
{
public:
//********************************************
null_message_router()
: imessage_router(imessage_router::NULL_MESSAGE_ROUTER)
{
}
//********************************************
null_message_router(etl::imessage_router& successor_)
: imessage_router(imessage_router::NULL_MESSAGE_ROUTER, successor_)
{
}
//********************************************
using etl::imessage_router::receive;
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
if (has_successor())
{
get_successor().receive(msg);
}
}
//********************************************
using etl::imessage_router::accepts;
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
if (has_successor())
{
return get_successor().accepts(id);
}
else
{
return false;
}
}
//********************************************
ETL_DEPRECATED
bool is_null_router() const ETL_OVERRIDE
{
return true;
}
//********************************************
bool is_producer() const ETL_OVERRIDE
{
return false;
}
//********************************************
bool is_consumer() const ETL_OVERRIDE
{
return false;
}
//********************************************
static null_message_router& instance()
{
static null_message_router nmr;
return nmr;
}
};
//***********************************************
/// null message router functionality.
inline etl::imessage_router& get_null_message_router()
{
return etl::null_message_router::instance();
}
//***************************************************************************
/// This router can be used as a producer-only of messages, such an interrupt
/// routine.
//***************************************************************************
class message_producer
: public imessage_router
, public private_message_router::traits<>
{
public:
//********************************************
message_producer()
: imessage_router(etl::imessage_router::MESSAGE_ROUTER)
{
}
//********************************************
message_producer(etl::imessage_router& successor_)
: imessage_router(imessage_router::NULL_MESSAGE_ROUTER, successor_)
{
}
//********************************************
message_producer(etl::message_router_id_t id_)
: imessage_router(id_)
{
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
}
//********************************************
message_producer(etl::message_router_id_t id_, etl::imessage_router& successor_)
: imessage_router(id_, successor_)
{
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
}
//********************************************
using etl::imessage_router::receive;
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
if (has_successor())
{
get_successor().receive(msg);
}
}
//********************************************
using etl::imessage_router::accepts;
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
if (has_successor())
{
return get_successor().accepts(id);
}
else
{
return false;
}
}
//********************************************
ETL_DEPRECATED
bool is_null_router() const ETL_OVERRIDE
{
return false;
}
//********************************************
bool is_producer() const ETL_OVERRIDE
{
return true;
}
//********************************************
bool is_consumer() const ETL_OVERRIDE
{
return false;
}
};
//***************************************************************************
/// Is T ultimately derived from etl::imessage_router?
//***************************************************************************
template <typename T>
struct is_message_router : public etl::bool_constant< etl::is_base_of< etl::imessage_router, typename etl::remove_cvref<T>::type>::value>
{
};
//***************************************************************************
/// Send a message to a router.
//***************************************************************************
template <typename TRouter, typename TMessage>
static typename etl::enable_if< etl::is_message_router<TRouter>::value && etl::is_message<TMessage>::value, void>::type
send_message(TRouter& destination, const TMessage& message)
{
destination.receive(message);
}
//***************************************************************************
/// Send a shared message to a router.
//***************************************************************************
template <typename TRouter>
static typename etl::enable_if<etl::is_message_router<TRouter>::value, void>::type send_message(TRouter& destination, etl::shared_message message)
{
destination.receive(message);
}
//***************************************************************************
/// Send a message to a router with a particular id.
//***************************************************************************
template <typename TRouter, typename TMessage>
static typename etl::enable_if< etl::is_message_router<TRouter>::value && etl::is_message<TMessage>::value, void>::type
send_message(TRouter& destination, etl::message_router_id_t id, const TMessage& message)
{
destination.receive(id, message);
}
//***************************************************************************
/// Send a shared message to a router with a particular id.
//***************************************************************************
template <typename TRouter>
static typename etl::enable_if<etl::is_message_router<TRouter>::value, void>::type send_message(TRouter& destination, etl::message_router_id_t id,
etl::shared_message message)
{
destination.receive(id, message);
}
//*************************************************************************************************
// For C++11 and above.
//*************************************************************************************************
#if ETL_USING_CPP11 && !defined(ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION)
//***************************************************************************
// The definition for all message types.
//***************************************************************************
template <typename TDerived, typename... TMessageTypes>
class message_router
: public imessage_router
, public private_message_router::traits<TMessageTypes...>
{
public:
using typename private_message_router::traits<TMessageTypes...>::message_packet;
using typename private_message_router::traits<TMessageTypes...>::message_types;
using typename private_message_router::traits< TMessageTypes...>::sorted_message_types;
//**********************************************
/// Default constructor. The message router id will be MESSAGE_ROUTER.
//**********************************************
message_router()
: imessage_router(etl::imessage_router::MESSAGE_ROUTER)
{
}
//**********************************************
/// Constructor with successor. The message router id will be
/// MESSAGE_ROUTER.
//**********************************************
message_router(etl::imessage_router& successor_)
: imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_)
{
}
//**********************************************
/// Constructor with message router id.
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
{
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
}
//**********************************************
/// Constructor with message router id and successor.
//**********************************************
message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
: imessage_router(id_, successor_)
{
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
}
//**********************************************
/// Allow visibility of base class receive() methods.
//**********************************************
using etl::imessage_router::receive;
//**********************************************
/// This will be called for all messages passed as an etl::imessage.
/// It will dispatch the message to the correct handler based on the message
/// id, or pass it to a successor if there is no handler for the message id.
/// \param msg The message.
//***********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
const etl::message_id_t id = msg.get_message_id();
// The IDs are sorted, so an ID less than the first is not handled by this
// router.
if (id >= Message_Id_Start)
{
const size_t index = get_dispatch_index_from_message_id(id);
// If the index is less than Number_Of_Messages, then we have a handler
// for this message type, so dispatch it.
if (index < Number_Of_Messages)
{
dispatch(msg, index);
return;
}
}
// We don't have a handler for this message type, so pass it to a
// successor if there is one, or call on_receive_unknown() if there isn't.
if (has_successor())
{
get_successor().receive(msg);
}
else
{
#include "etl/private/diagnostic_array_bounds_push.h"
static_cast<TDerived*>(this)->on_receive_unknown(msg);
#include "etl/private/diagnostic_pop.h"
}
}
//**********************************************
/// This will be called for messages where TMessage is in the message type
/// list. \tparam TMessage The message type. \param msg The message. Enabled
/// if TMessage is in the message type list.
//**********************************************
template < typename TMessage, typename etl::enable_if<etl::is_one_of<TMessage, TMessageTypes...>::value, int>::type = 0>
void receive(const TMessage& msg)
{
#include "etl/private/diagnostic_array_bounds_push.h"
static_cast<TDerived*>(this)->on_receive(msg);
#include "etl/private/diagnostic_pop.h"
}
//**********************************************
/// This will be called for messages where TMessage is a message type, but
/// not in the message type list. \tparam TMessage The message type. \param
/// msg The message. Enabled if TMessage is a message type, but not in the
/// message type list.
//**********************************************
template <typename TMessage,
typename etl::enable_if< etl::is_message<TMessage>::value && !etl::is_one_of<TMessage, TMessageTypes...>::value, int>::type = 0>
void receive(const TMessage& msg)
{
if (has_successor())
{
get_successor().receive(msg);
}
else
{
#include "etl/private/diagnostic_array_bounds_push.h"
static_cast<TDerived*>(this)->on_receive_unknown(msg);
#include "etl/private/diagnostic_pop.h"
}
}
//**********************************************
/// Allow visibility of base class accepts() methods.
//**********************************************
using imessage_router::accepts;
//**********************************************
/// This will return true if the message id is in the message type list, or
/// if a successor accepts the message id.
//***********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
if (id >= Message_Id_Start)
{
const size_t index = get_dispatch_index_from_message_id(id);
if (index < Number_Of_Messages)
{
return true;
}
}
return has_successor() ? get_successor().accepts(id) : false;
}
//********************************************
ETL_DEPRECATED
bool is_null_router() const ETL_OVERRIDE
{
return false;
}
//********************************************
bool is_producer() const ETL_OVERRIDE
{
return true;
}
//********************************************
bool is_consumer() const ETL_OVERRIDE
{
return true;
}
private:
static constexpr size_t Number_Of_Messages = sizeof...(TMessageTypes);
static constexpr etl::message_id_t Message_Id_Start = etl::type_list_type_at_index_t<sorted_message_types, 0>::ID;
//**********************************************
// Checks that the message ids are contiguous.
//**********************************************
template <size_t Index, bool Last = (Index + 1U >= Number_Of_Messages)>
struct contiguous_impl;
template <size_t Index>
struct contiguous_impl<Index, true> : etl::true_type
{
};
template <size_t Index>
struct contiguous_impl<Index, false>
: etl::bool_constant< (etl::type_list_type_at_index_t<sorted_message_types, Index>::ID + 1U
== etl::type_list_type_at_index_t<sorted_message_types, Index + 1U>::ID)
&& contiguous_impl<Index + 1U>::value>
{
};
// The message ids are contiguous if there are 0 or 1 message types, or if
// each message id is one greater than the previous message id.
static constexpr bool Message_Ids_Are_Contiguous = (Number_Of_Messages <= 1U) ? true : contiguous_impl<0U>::value;
using handler_ptr = void (*)(TDerived&,
const etl::imessage&); ///< Pointer to a handler function that
///< takes a reference to the derived
///< class and a reference to the message.
using message_dispatch_table_t = etl::array<handler_ptr,
Number_Of_Messages>; ///< The dispatch table type. An array of
///< handler pointers, one for each
///< message type.
using message_id_table_t = etl::array<etl::message_id_t,
Number_Of_Messages>; ///< The message id table type. An
///< array of message ids, one for
///< each message type.
//**********************************************
// Call for a single message type
//**********************************************
template <typename TMessage>
static void call_on_receive(TDerived& derived, const imessage& msg)
{
derived.on_receive(static_cast<const TMessage&>(msg));
}
//**********************************************
// Get the handler for a single message type at the index in the sorted
// type_list. This will be called for each message type to generate the
// dispatch table.
//**********************************************
template <size_t Index>
static constexpr handler_ptr get_message_handler()
{
return &call_on_receive< etl::type_list_type_at_index_t<sorted_message_types, Index>>;
}
//**********************************************
// Generate the dispatch table at compile time.
// This will create an array of handler pointers, one for each message type.
//**********************************************
template <size_t... Indices>
static constexpr message_dispatch_table_t make_message_dispatch_table(etl::index_sequence<Indices...>)
{
return message_dispatch_table_t{{get_message_handler<Indices>()...}};
}
//**********************************************
// Get the message id for a single message type at an index in the sorted
// type_list. This will be called for each message type to generate the
// message id table.
//**********************************************
template <size_t Index>
static constexpr etl::message_id_t get_message_id_from_index()
{
return etl::type_list_type_at_index_t<sorted_message_types, Index>::ID;
}
//**********************************************
// Generate the message id table at compile time.
// This will create an array of message ids, one for each message type.
//**********************************************
template <size_t... Indices>
static constexpr message_id_table_t make_message_id_table(etl::index_sequence<Indices...>)
{
return message_id_table_t{{get_message_id_from_index<Indices>()...}};
}
//**********************************************
// Get the dispatch index for a message id.
// This will be used at runtime to find the handler for a message id.
// If the message ids are contiguous, we can calculate the index directly.
// If they are not contiguous, we need to do a binary search. This will
// return Number_Of_Messages if the message id is not found, which indicates
// that the message should be passed to the successor.
//**********************************************
static size_t get_dispatch_index_from_message_id(etl::message_id_t id)
{
if ETL_IF_CONSTEXPR (Message_Ids_Are_Contiguous)
{
// The IDs are contiguous, so we can calculate the index directly.
return static_cast<size_t>(id - Message_Id_Start);
}
else
{
// The IDs are not contiguous, so we need to do a binary search.
size_t left = 0;
size_t right = Number_Of_Messages;
while (left < right)
{
size_t mid = (left + right) / 2;
if (message_id_table[mid] == id)
{
return mid;
}
else if (message_id_table[mid] < id)
{
left = mid + 1;
}
else
{
right = mid;
}
}
}
return Number_Of_Messages; // Not found
}
//**********************************************
// Dispatch the message to the appropriate handler based on the index in the
// dispatch table.
//**********************************************
void dispatch(const etl::imessage& msg, size_t index)
{
message_dispatch_table[index](static_cast<TDerived&>(*this), msg);
}
//**********************************************
// The dispatch table is generated at compile time. The dispatch table
// contains pointers to the on_receive handlers for each message type.
//**********************************************
static ETL_INLINE_VAR constexpr message_dispatch_table_t message_dispatch_table =
etl::message_router<TDerived, TMessageTypes...>::make_message_dispatch_table(
etl::make_index_sequence< etl::message_router< TDerived, TMessageTypes...>::Number_Of_Messages>{});
//**********************************************
// The message id table is generated at compile time. The message id table
// contains the corresponding message ids for each message type.
//**********************************************
static ETL_INLINE_VAR constexpr message_id_table_t message_id_table = etl::message_router<TDerived, TMessageTypes...>::make_message_id_table(
etl::make_index_sequence< etl::message_router< TDerived, TMessageTypes...>::Number_Of_Messages>{});
};
#if ETL_USING_CPP11 && !ETL_USING_CPP17
template <typename TDerived, typename... TMessageTypes>
constexpr const typename etl::message_router< TDerived, TMessageTypes...>::message_dispatch_table_t
etl::message_router<TDerived, TMessageTypes...>::message_dispatch_table;
template <typename TDerived, typename... TMessageTypes>
constexpr const typename etl::message_router< TDerived, TMessageTypes...>::message_id_table_t
etl::message_router<TDerived, TMessageTypes...>::message_id_table;
#endif
//***************************************************************************
// The definition of a message_router for zero message types.
//***************************************************************************
template <typename TDerived>
class message_router<TDerived>
: public imessage_router
, public private_message_router::traits<>
{
public:
//**********************************************
/// Default constructor. The message router id will be MESSAGE_ROUTER.
//**********************************************
message_router()
: imessage_router(etl::imessage_router::MESSAGE_ROUTER)
{
}
//**********************************************
/// Constructor with successor. The message router id will be
/// MESSAGE_ROUTER.
//**********************************************
message_router(etl::imessage_router& successor_)
: imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_)
{
}
//**********************************************
/// Constructor with message router id.
//**********************************************
message_router(etl::message_router_id_t id_)
: imessage_router(id_)
{
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
}
//**********************************************
/// Constructor with message router id and successor.
//**********************************************
message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
: imessage_router(id_, successor_)
{
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
}
//**********************************************
/// Allow visibility of base class receive() methods.
using etl::imessage_router::receive;
//**********************************************
/// This will be called for all messages passed as an etl::imessage.
/// Since there are no message types, this will just pass the message to a
/// successor if there is one, or call on_receive_unknown() if there isn't.
/// \param msg The message.
//***********************************************
void receive(const etl::imessage& msg) ETL_OVERRIDE
{
#include "etl/private/diagnostic_array_bounds_push.h"
if (has_successor())
{
get_successor().receive(msg);
}
#include "etl/private/diagnostic_pop.h"
}
//**********************************************
/// Allow visibility of base class accepts() methods.
//**********************************************
using imessage_router::accepts;
//**********************************************
/// This will return true if a successor accepts the message id.
//***********************************************
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
{
if (has_successor())
{
return get_successor().accepts(id);
}
else
{
return false;
}
}
//********************************************
ETL_DEPRECATED
bool is_null_router() const ETL_OVERRIDE
{
return false;
}
//********************************************
bool is_producer() const ETL_OVERRIDE
{
return true;
}
//********************************************
bool is_consumer() const ETL_OVERRIDE
{
return true;
}
};
//***************************************************************************
/// Helper to turn etl::type_list<TTypes...> into
/// etl::message_router<TTypes...>
//***************************************************************************
template <typename TDerived, typename TList>
struct message_router_from_type_list;
template <typename TDerived, typename... TMessageTypes>
struct message_router_from_type_list<TDerived, etl::type_list<TMessageTypes...>>
{
using type = etl::message_router<TDerived, TMessageTypes...>;
};
template <typename TDerived, typename TTypeList>
using message_router_from_type_list_t = typename message_router_from_type_list<TDerived, TTypeList>::type;
#else
#include "private/message_router_cpp03.h"
#endif
} // namespace etl
// message_router is a typedef of message_processor, which is the new name for this class.
// The old name is kept for backwards compatibility.
#include "message_processor.h"
#endif

View File

@ -42,7 +42,8 @@ namespace etl
typedef ETL_MESSAGE_ID_TYPE message_id_t;
#endif
typedef uint_least8_t message_router_id_t;
typedef uint_least8_t message_router_id_t;
typedef message_router_id_t message_processor_id_t;
} // namespace etl
#endif

View File

@ -3563,6 +3563,7 @@
<ClInclude Include="..\..\include\etl\lcm.h" />
<ClInclude Include="..\..\include\etl\math.h" />
<ClInclude Include="..\..\include\etl\message_broker.h" />
<ClInclude Include="..\..\include\etl\message_processor.h" />
<ClInclude Include="..\..\include\etl\monostate.h" />
<ClInclude Include="..\..\include\etl\not_null.h" />
<ClInclude Include="..\..\include\etl\poly_span.h" />
@ -11807,4 +11808,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -1572,6 +1572,9 @@
<ClInclude Include="..\..\include\etl\format.h">
<Filter>UnitTest++\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\message_processor.h">
<Filter>ETL\Messaging</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\test_string_char.cpp">
@ -4124,4 +4127,4 @@
<Filter>Resource Files\Images</Filter>
</Image>
</ItemGroup>
</Project>
</Project>