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

Message Bus

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.

etl::imessage_bus

The base for all message buses.
Inherits publicly from etl::message_router.
Message buses are therefore also a type of  router.
Objects of type etl::imessage_bus cannot be directly constructed.

Member functions

bool subscribe(etl::imessage_router& router);
Subscribes an etl::imessage_router derived class to the bus.
Returns true on success.
_______________________________________________________________________________________

void unsubscribe(etl::imessage_router& router);
Unsubscribes the specified etl::imessage_router derived class from the bus.
Does not unsubscribe from nested buses.
_______________________________________________________________________________________

void unsubscribe(etl::message_router_id_t id)
Unsubscribes routers with the specified id from the bus.
Does not unsubscribe from nested buses.

etl::imessage::MESSAGE_BUS will unsubscribe all message buses.
etl::imessage::ALL_MESSAGE_ROUTERS will unsubscribe all routers and buses. Equivalent to calling clear().
_______________________________________________________________________________________

void receive(const etl::imessage& message);
Receives a message and distributes it to all subscribers.
Forwards the message to all nested message buses.

The routers are called first, in order of ascending router id.
Routers with the duplicate ids will be called in subscribe order.
Any nested message buses are called in subscribe order.
_______________________________________________________________________________________

void receive(etl::message_router_id_t destination_router_id,
             const etl::imessage&     message);
Receives a message and distributes it to all subscribers that have the specified router id.
Forwards the message to all nested message buses.

Routers with the duplicate ids will be called in subscribe order.
Any nested message buses are called in subscribe order.
_______________________________________________________________________________________

void receive(etl::imessage_router& sender,
             const etl::imessage&  message);
Receives a message and distributes it to all subscribers.
Specifies the sender router.
Forwards the message to all nested message buses.

The routers are called first, in order of ascending router id.
Routers with the duplicate ids will be called in subscribe order.
Any nested message buses are called in subscribe order.
_______________________________________________________________________________________

void receive(etl::imessage_router&    sender,
             etl::message_router_id_t destination_router_id,
             const etl::imessage&     message)
Receives a message and distributes it to all subscribers that have the specified router id.
Specifies the sender router
Forwards the message to all nested message buses.

Routers with the duplicate ids will be called in subscribe order.
Any nested message buses are called in subscribe order.
_______________________________________________________________________________________

bool accepts(etl::message_id_t id) const;
Always returns true.
_______________________________________________________________________________________

size_t size() const;
Returns the number of subscribers.
_______________________________________________________________________________________

void clear();
Clears the bus of all subscribers.
_______________________________________________________________________________________

Message buses inherit all of the public functions of etl::imessage_router.

Errors

message_bus_exception
Base error class for etl::message_bus. Inherits from etl::exception

message_bus_too_many_subscribers
Emitted when the number of subscribers exceeds the capacity. Inherits from etl::message_bus_exception.

etl::message_bus

Inherits publicly from etl::imessage_bus.

Template Parameters

uint_least8_t MAX_ROUTERS
The maximum number of routers that can be subscribed.

Member functions

message_bus()
Constructs a message bus.
Message buses always have a router id of etl::imessage::MESSAGE_BUS.

Global functions

void send_message(etl::imessage_bus&   bus,
                  const etl::imessage& message);
Broadcast the message to all subscribers of bus1.
_______________________________________________________________________________________

void send_message(etl::imessage_router&    sender,
                  etl::imessage_bus&       bus,
                  etl::message_router_id_t id,
                  const etl::imessage&     message);
Address the message to all subscribers of bus1 with id.
_______________________________________________________________________________________

void send_message(etl::imessage_router& sender,
                  etl::imessage_bus&    bus,
                  const etl::imessage&  message);
Broadcast the message to all subscribers of bus1 from the sender.
_______________________________________________________________________________________

void send_message(etl::imessage_router&    sender,
                  etl::imessage_bus&       bus,
                  etl::message_router_id_t id,
                  const etl::imessage&     message);
Address the message to all subscribers of bus1 with id from the sender.

Example

// Some router ids.
enum
{
  ROUTER_ID_1,
  ROUTER_ID_2,
  ROUTER_ID_3
};

// Instances of messages.
MessageA messageA;

// Instances of message routers.
RouterA routerA(ROUTER_ID_1);
RouterB routerB(ROUTER_ID_1);
RouterC routerC(ROUTER_ID_2);
RouterD routerD(ROUTER_ID_3);
RouterE routerE(ROUTER_ID_1);

// Instances of message buses.
etl::message_bus<4> bus1;
etl::message_bus<2> bus2;
etl::message_bus<1> bus3;

// Subscribe bus2 & bus3 to bus1.
bus1.subscribe(bus3);
bus1.subscribe(bus2);

// Subscribe routerB & routerA to bus1.
bus1.subscribe(routerB);
bus1.subscribe(routerA);

// Subscribe routerD & routerC to bus2.
bus2.subscribe(routerD);
bus2.subscribe(routerC);

// Subscribe routerE to bus3.
bus3.subscibe(routerE);

// Assume all routers accept the same messages.

// Broadcast messageA to everyone.
bus1.receive(messageA);

The call order will be...
routerB
routerA
routerE
routerC
routerD

// Address messageA to routers with id ROUTER_ID_1.
bus1.receive(ROUTER_ID_1, messageA);

The call order will be...
routerB
routerA
routerE

// Address messageA to routers with id ROUTER_ID_3.
bus1.receive(ROUTER_ID_1, messageA);

The call order will be...
routerD
message_bus.h