A C++ template library for embedded applications
Designed and maintained by
Aster Consulting Ltd

Message Router

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. If a sender router is not specified then the on_receive function is passed an instance of
etl::null:message_router.

The on_receive functions are not virtual. The template class uses CRTP to directly call the derived class's functions.

Defines the following classes:-
etl::imessage_router
etl::message_router
etl::null_message_router

etl::imessage_router

The base class for all routers.


Member functions

virtual ~imessage_router() {}

virtual void receive(const etl::imessage& message) = 0;
Receive a message.
Overridden by the derived class.

virtual void receive(imessage_router& sender, const etl::imessage& message) = 0;
Receive a message from a defined sender.
Overridden by the derived class.

virtual bool accepts(etl::message_id_t id) const = 0;
Returns true if the router accepts the message id.
Overridden by the derived class.

bool accepts(const etl::imessage& msg) const;
Returns true if the router accepts the message.

etl::message_router_id_t get_message_router_id() const;
Returns the router id.

Enumerations

NULL_MESSAGE_ROUTER
MESSAGE_BUS
ALL_MESSAGE_ROUTERS
MAX_MESSAGE_ROUTER

etl::message_router

Template parameters

TDerived The derived class.
T1       The first message type.
T2...    The additional message types.
         The maximum number of types can be set by running the generator for this file. The default is 16

The derived class must define the following member functions.

void on_receive(etl::imessage_router& sender, const Type& msg);
Replace Type with the concrete message type.
And so on for all of the template parameter types.

void on_receive_unknown(etl::imessage_router& sender, const etl::imessage& msg);
Called when a message type is received that is not in the template list.

Member classes

message_packet

A class that can hold any of messages declared in the template parameter list.
Maybe useful for use in message queues for this class.

template <typename T>
explicit message_packet(const T& msg);
Copies a message to the packet.
Static asserts if T is not one of those in the template parameter list.

~message_packet()
Destructs the packet and its contents.

etl::imessage& get()
const etl::imessage& get() const
Gets a reference to the contained message.

SIZE      The size of the largest type.
ALIGNMENT The largest alignment of all of the types.

Member functions

message_router(etl::message_router_id_t id);
Constructs the router.
The router id must be between 0 and 249. Ids 250 to 255 are reserved for ETL use.
Emits an error if the id is outside the legal range.
Routers may have duplicate ids.
_______________________________________________________________________________________

void receive(const etl::imessage& msg);
Receive a message.
_______________________________________________________________________________________

void receive(etl::imessage_router& sender, const etl::imessage& msg);
Receive a message from a defined sender router.
_______________________________________________________________________________________

bool accepts(etl::message_id_t id) const;
Returns true if the router accepts the message id.
_______________________________________________________________________________________

Errors

message_router_exception
Base exception for router errors.
Derived from etl::exception.
_______________________________________________________________________________________

message_router_illegal_id
The router id is out of the legal range.
Derived from etl::message_router_exception
_______________________________________________________________________________________

etl::null_message_router
This message router may either be a sink for messages or be the router for components that only ever emit messages.

null_message_router()
Constructs a null message router.
The router id will be etl::imessage_router::NULL_MESSAGE_ROUTER.
_______________________________________________________________________________________

void receive(const etl::imessage& message);
Receives a message.
Does nothing.
_______________________________________________________________________________________

void receive(etl::imessage_router& source, const etl::imessage& message);
Receives a message.
Does nothing.
_______________________________________________________________________________________

bool accepts(etl::message_id_t id) const;
Returns false.
_______________________________________________________________________________________

static null_message_router& instance()
Returns an instance of etl::null_message_router.
_______________________________________________________________________________________

Global functions

void send_message(etl::imessage_router& destination,
                  const etl::imessage&  message);
_______________________________________________________________________________________

void send_message(etl::imessage_router& source,
                  etl::imessage_router& destination,
                  const etl::imessage&  message);
_______________________________________________________________________________________

Example

// Message ids.
enum
{
  START,
  STOP,
  SET_SPEED
};

// The start message.
struct Start : public etl::message<START>
{
};

// The stop message.
struct Stop : public etl::message<STOP>
{
};

// The set speed message.
struct SetSpeed : public etl::message<SET_SPEED>
{
  SetSpeed(uint32_t speed_)
    : speed(speed_)
  {
  }

  uint32_t speed;
};

// The router.
class Router : etl::message_router<Router, Start, Stop, SetSpeed>
{
public:

  // Construct the router with an id of 0.
  Router()
    : message_router(0)
  {
  }

  // Received a start message.
  void on_receive(etl::imessage_router& sender, const Start& msg)
  {
    std::cout << "Start message received\n";
  }

  // Received a stop message.
  void on_receive(etl::imessage_router& sender, const Stop& msg)
  {
    std::cout << "Start message received\n";
  }

  // Received a set speed message.
  void on_receive(etl::imessage_router& sender, const SetSpeed& msg)
  {
    std::cout << "SetSpeed(" << msg.speed << ") message received\n";
  }

  // Received an unknown message.
  void on_receive_unknown(etl::imessage_router& sender, const etl::imessage& msg)
  {
    std::cout << "Unknown message " << msg.get_message_id() << " received\n";
  }
}

// Router and message instances.
Router   router;
Start    start;
Stop     stop;
SetSpeed halfSpeed(50);
SetSpeed maxSpeed(100);

// A queue for Router messages.
etl::queue<Router::message_packet, 10> queue;

// Add to the queue.
queue.emplace(start);
queue.emplace(stop);
queue.emplace(maxSpeed);
queue.emplace(halfSpeed);

// Send the queued messages to 'router'.
while (!queue.empty())
{
  etl::send_message(router, queue.front().get());
  queue.pop();
}
message_router.h