message.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #pragma once
  2. //
  3. // Copyright (c) 2019-2022 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. #if defined(_MSC_VER)
  12. #pragma warning(push)
  13. #pragma warning(disable : 4251)
  14. #endif
  15. namespace rotor {
  16. /** \struct message_base_t
  17. * \brief Base class for `rotor` message.
  18. *
  19. * The base class contains destinanation address (in the form of intrusive
  20. * pointer to `address_t`) and possibility to detect final message type.
  21. *
  22. * The actual message payload meant to be provided by derived classes
  23. *
  24. */
  25. struct message_base_t : public arc_base_t<message_base_t> {
  26. virtual ~message_base_t() = default;
  27. /**
  28. * \brief unique message type pointer.
  29. *
  30. * The unique message type pointer is used to runtime check message type
  31. * match when the message is delivered to subscribers.
  32. *
  33. */
  34. const void *type_index;
  35. /** \brief message destination address */
  36. address_ptr_t address;
  37. /** \brief constructor which takes destination address */
  38. inline message_base_t(const void *type_index_, const address_ptr_t &addr)
  39. : type_index(type_index_), address{addr} {}
  40. };
  41. namespace message_support {
  42. ROTOR_API const void *register_type(const std::type_index &type_index) noexcept;
  43. }
  44. /** \struct message_t
  45. * \brief the generic message meant to hold user-specific payload
  46. * \tparam T payload type
  47. */
  48. template <typename T> struct message_t : public message_base_t {
  49. /** \brief alias for payload type */
  50. using payload_t = T;
  51. /** \brief forwards `args` for payload construction */
  52. template <typename... Args>
  53. message_t(const address_ptr_t &addr, Args &&...args)
  54. : message_base_t{message_type, addr}, payload{std::forward<Args>(args)...} {}
  55. /** \brief user-defined payload */
  56. T payload;
  57. /** \brief unique per-message-type pointer used for routing */
  58. static const void *message_type;
  59. };
  60. template <typename T> const void *message_t<T>::message_type = message_support::register_type(typeid(message_t<T>));
  61. /** \brief intrusive pointer for message */
  62. using message_ptr_t = intrusive_ptr_t<message_base_t>;
  63. /** \brief structure to hold messages (intrusive pointers) */
  64. using messages_queue_t = std::deque<message_ptr_t>;
  65. /** \brief constucts message by constructing it's payload; intrusive pointer for the message is returned */
  66. template <typename M, typename... Args> auto make_message(const address_ptr_t &addr, Args &&...args) -> message_ptr_t {
  67. return message_ptr_t{new message_t<M>(addr, std::forward<Args>(args)...)};
  68. }
  69. } // namespace rotor
  70. #if defined(_MSC_VER)
  71. #pragma warning(pop)
  72. #endif