ETLCPP / etl

Embedded Template Library
https://www.etlcpp.com
MIT License
2.04k stars 371 forks source link

how to combine message_broker with message_bus #888

Closed CodingPapi closed 2 months ago

CodingPapi commented 2 months ago

Hi, I want to only send specific messages to specific message_bus, and then the bus dispatch msg to routers subscribed on it.

I tried use a message_broker as the root, and it seems it only works with message_router which can have a user defined router id.

Could you please give me some advise on this ? thanks!

jwellbelove commented 2 months ago

Unless I were to change the code to allow message busses to have unique IDs or adding a receive overload that takes a reference to a message router type, one way would be to do something like this, where you create your own simple message broker derived from etl::imessage_router.

enum MessageIDs
{
    Message1,
    Message2,
    Message3,
    Message4,
    Message5,
    Message6
};

class message1 : public etl::message<Message1> {};
class message2 : public etl::message<Message2> {};
class message3 : public etl::message<Message3> {};
class message4 : public etl::message<Message4> {};
class message5 : public etl::message<Message5> {};
class message6 : public etl::message<Message6> {};

class MyMessageBroker : public etl::imessage_router
{
public:

  MyMessageBroker()
    : imessage_router(0)
  {
  }

  void receive(const etl::imessage& msg)
  {
    switch (msg.get_message_id())
    {
      case Message1:
      case Message2:
      case Message3:
      {
        messageBus1.receive(msg);
        break;
      }

      case Message4:
      case Message5:
      case Message6:
      {
        messageBus2.receive(msg);
        break;
      }

      default:
      {
        if (has_successor())
        {
          get_successor().receive(msg);
        }
        break;
      }
    }
  }

  bool accepts(etl::message_id_t id) const
  {
    switch (id)
    {
      case Message1:
      case Message2:
      case Message3:
      case Message4:
      case Message5:
      case Message6:
      {
        return true;
      }

      default:
      {
        return false;
      }
    }
  }

  bool is_null_router() const
  {
    return false;
  }

  bool is_producer() const
  {
    return true;
  }

  bool is_consumer() const
  {
    return true;
  }

  etl::message_bus<10> messageBus1;
  etl::message_bus<10> messageBus2;
};
jwellbelove commented 2 months ago

An alternative is to base it on etl::message_router.

enum MessageIDs
{
  Message1,
  Message2,
  Message3,
  Message4,
  Message5,
  Message6
};

class message1 : public etl::message<Message1> {};
class message2 : public etl::message<Message2> {};
class message3 : public etl::message<Message3> {};
class message4 : public etl::message<Message4> {};
class message5 : public etl::message<Message5> {};
class message6 : public etl::message<Message6> {};

class MyMessageBroker : public etl::message_router<MyMessageBroker, message1, message2, message3, message4, message5, message6>
{
public:

  MyMessageBroker()
    : message_router(0)
  {
  }

  void on_receive(const message1& msg)
  {
     messageBus1.receive(msg);
  }

  void on_receive(const message2& msg)
  {
    messageBus1.receive(msg);
  }

  void on_receive(const message3& msg)
  {
    messageBus1.receive(msg);
  }

  void on_receive(const message4& msg)
  {
    messageBus2.receive(msg);
  }

  void on_receive(const message5& msg)
  {
    messageBus2.receive(msg);
  }

  void on_receive(const message6& msg)
  {
    messageBus2.receive(msg);
  }

  void on_receive_unknown(const etl::imessage& msg)
  {

  }

  etl::message_bus<10> messageBus1;
  etl::message_bus<10> messageBus2;
};
CodingPapi commented 2 months ago

Thank you for your quick reply, I will try.