message.h 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. #pragma once
  2. //
  3. // Copyright (c) 2019-2020 Ivan Baidakou (basiliscos) (the dot dmol at gmail dot com)
  4. //
  5. // Distributed under the MIT Software License
  6. //
  7. #include "arc.hpp"
  8. #include "address.hpp"
  9. #include <typeindex>
  10. #include <deque>
  11. namespace rotor {
  12. /** \struct message_base_t
  13. * \brief Base class for `rotor` message.
  14. *
  15. * The base class contains destinanation address (in the form of intrusive
  16. * pointer to `address_t`) and possibility to detect final message type.
  17. *
  18. * The actual message payload meant to be provided by derived classes
  19. *
  20. */
  21. struct message_base_t : public arc_base_t<message_base_t> {
  22. virtual ~message_base_t();
  23. /**
  24. * \brief unique message type pointer.
  25. *
  26. * The unique message type pointer is used to runtime check message type
  27. * match when the message is delivered to subscribers.
  28. *
  29. */
  30. const void *type_index;
  31. /** \brief message destination address */
  32. address_ptr_t address;
  33. /** \brief constructor which takes destination address */
  34. message_base_t(const void *type_index_, const address_ptr_t &addr) : type_index{type_index_}, address{addr} {}
  35. };
  36. inline message_base_t::~message_base_t() {}
  37. /** \struct message_t
  38. * \brief the generic message meant to hold user-specific payload
  39. * \tparam T payload type
  40. */
  41. template <typename T> struct message_t : public message_base_t {
  42. /** \brief alias for payload type */
  43. using payload_t = T;
  44. /** \brief forwards `args` for payload construction */
  45. template <typename... Args>
  46. message_t(const address_ptr_t &addr, Args &&...args)
  47. : message_base_t{message_type, addr}, payload{std::forward<Args>(args)...} {}
  48. /** \brief user-defined payload */
  49. T payload;
  50. /** \brief static type which uniquely identifies payload-type specialized `message_t` */
  51. static const void *message_type;
  52. };
  53. /** \brief intrusive pointer for message */
  54. using message_ptr_t = intrusive_ptr_t<message_base_t>;
  55. /** \brief structure to hold messages (intrusive pointers) */
  56. using messages_queue_t = std::deque<message_ptr_t>;
  57. template <typename T> const void *message_t<T>::message_type = static_cast<const void *>(typeid(message_t<T>).name());
  58. /** \brief constucts message by constructing it's payload; intrusive pointer for the message is returned */
  59. template <typename M, typename... Args> auto make_message(const address_ptr_t &addr, Args &&...args) -> message_ptr_t {
  60. return message_ptr_t{new message_t<M>(addr, std::forward<Args>(args)...)};
  61. }
  62. } // namespace rotor