subscription.h 3.0 KB

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