subscription.h 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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 "rotor/forward.hpp"
  8. #include "rotor/address.hpp"
  9. #include "rotor/subscription_point.h"
  10. #include "rotor/message.h"
  11. #include <boost/unordered_map.hpp>
  12. #include <vector>
  13. #if defined(_MSC_VER)
  14. #pragma warning(push)
  15. #pragma warning(disable : 4251)
  16. #endif
  17. namespace rotor {
  18. /** \struct subscription_t
  19. * \brief Holds and classifies message handlers on behalf of supervisor
  20. *
  21. * The handlers are classified by message type and by the source supervisor, i.e.
  22. * whether the handler's supervisor is external or not.
  23. *
  24. */
  25. struct ROTOR_API subscription_t {
  26. /** \brief alias for message type (i.e. stringized typeid) */
  27. using message_type_t = const void *;
  28. /** \brief vector of handler pointers */
  29. using handlers_t = std::vector<handler_base_t *>;
  30. /** \struct joint_handlers_t
  31. * \brief pair internal and external {@link handler_t}
  32. */
  33. struct joint_handlers_t {
  34. /** \brief internal handlers, i.e. those which belong to actors of the supervisor */
  35. handlers_t internal;
  36. /** \brief external handlers, i.e. those which belong to actors of other supervisor */
  37. handlers_t external;
  38. };
  39. subscription_t() noexcept;
  40. /** \brief upgrades subscription_point_t into subscription_info smart pointer
  41. *
  42. * Performs the classification of the point, i.e. whether handler and address
  43. * are internal or external, records the state subscription state and records
  44. * the handler among address handlers.
  45. *
  46. */
  47. subscription_info_ptr_t materialize(const subscription_point_t &point) noexcept;
  48. /** \brief sets new handler for the subscription point */
  49. void update(subscription_point_t &point, handler_ptr_t &new_handler) noexcept;
  50. /** \brief remove subscription_info from `internal_infos` and `mine_handlers` */
  51. void forget(const subscription_info_ptr_t &info) noexcept;
  52. /** \brief returns list of all handlers for the message (internal and external) */
  53. const joint_handlers_t *get_recipients(const message_base_t &message) const noexcept;
  54. /** \brief generic non-public fields accessor */
  55. template <typename T> auto &access() noexcept;
  56. private:
  57. struct subscription_key_t {
  58. address_t *address;
  59. message_type_t message_type;
  60. inline bool operator==(const subscription_key_t &other) const noexcept {
  61. return address == other.address && message_type == other.message_type;
  62. }
  63. };
  64. struct subscription_key_hash_t {
  65. inline std::size_t operator()(const subscription_key_t &k) const noexcept {
  66. return std::size_t(k.address) + 0x9e3779b9 + (size_t(k.message_type) << 6) + (size_t(k.message_type) >> 2);
  67. }
  68. };
  69. using addressed_handlers_t = boost::unordered_map<subscription_key_t, joint_handlers_t, subscription_key_hash_t>;
  70. using info_container_t = boost::unordered_map<address_ptr_t, std::vector<subscription_info_ptr_t>>;
  71. address_t *main_address;
  72. info_container_t internal_infos;
  73. addressed_handlers_t mine_handlers;
  74. };
  75. } // namespace rotor
  76. #if defined(_MSC_VER)
  77. #pragma warning(pop)
  78. #endif