plugin_base.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. #pragma once
  2. //
  3. // Copyright (c) 2019-2021 Ivan Baidakou (basiliscos) (the dot dmol at gmail dot com)
  4. //
  5. // Distributed under the MIT Software License
  6. //
  7. #include "../subscription.h"
  8. #include "rotor/messages.hpp"
  9. namespace rotor::plugin {
  10. enum class config_phase_t { PREINIT = 0b01, INITIALIZING = 0b10 };
  11. /** \struct plugin_base_t
  12. *
  13. * \brief base class for all actor plugins
  14. *
  15. */
  16. struct plugin_base_t {
  17. /** \brief possible plugin's reactions on actor lifetime events */
  18. enum reaction_t {
  19. INIT = 1 << 0,
  20. SHUTDOWN = 1 << 1,
  21. SUBSCRIPTION = 1 << 2,
  22. START = 1 << 3,
  23. };
  24. /** \brief default plugin ctor */
  25. plugin_base_t() = default;
  26. /** \brief copy ctor is not allowed */
  27. plugin_base_t(const plugin_base_t &) = delete;
  28. virtual ~plugin_base_t() = default;
  29. /** \brief returns pointer, which uniquely identifes plugin type */
  30. virtual const void *identity() const noexcept = 0;
  31. /** \brief invoked by actor upon initialization.
  32. *
  33. * It it responsible for setting up reactions and further installation, e.g.
  34. * messages subscriptions and may calling back actor's configuration
  35. * (which can be postponed).
  36. *
  37. * Before the activate is invoked, the plugin is in `PREINIT` phase,
  38. * after the activate is called, the plugin is in `INITIALIZING` phase.
  39. * This might be useful for early/late (double) plugin configuration
  40. * in actor.
  41. */
  42. virtual void activate(actor_base_t *actor) noexcept;
  43. /** \brief deactivates plugin from an actor
  44. *
  45. * The method can be intercepted by descendants to do not deactivate
  46. * too early, and called when needed.
  47. *
  48. * The `plugin_base_t` implementation unsubscribes from all plugin
  49. * subscriptions and when no subscription left commits deactivation
  50. * to an actor.
  51. *
  52. */
  53. virtual void deactivate() noexcept;
  54. /** \brief polls plugin, whether it is done with initialization
  55. *
  56. * The method is invoked only when `init` reaction was set on.
  57. *
  58. * The `true` is returned, that means plugin is done with init and
  59. * will not be longer polled in future.
  60. *
  61. */
  62. virtual bool handle_init(message::init_request_t *message) noexcept;
  63. /** \brief polls plugin, whether it is done with shutdown
  64. *
  65. * The method is invoked only when `shutdown` reaction was set on.
  66. *
  67. * The `true` is returned, that means plugin is done with shutdown and
  68. * will not be longer polled in future.
  69. *
  70. */
  71. virtual bool handle_shutdown(message::shutdown_request_t *message) noexcept;
  72. /** \brief polls plugin, whether it is done with start
  73. *
  74. * The method is invoked only when `start` reaction was set on.
  75. *
  76. * The `true` is returned, that means plugin is done with start and
  77. * will not be longer polled in future.
  78. *
  79. */
  80. virtual void handle_start(message::start_trigger_t *message) noexcept;
  81. /** \brief polls plugin, whether it is done with subscription
  82. *
  83. * The method is invoked only when `subscription` reaction was set on.
  84. *
  85. * The `true` is returned, that means plugin is done with start and
  86. * will not be longer polled in future.
  87. *
  88. */
  89. virtual bool handle_subscription(message::subscription_t &message) noexcept;
  90. /** \brief polls plugin, whether it is done with unsubscription
  91. *
  92. * All plugins are polled for unsubscription, no special handling is
  93. * needed unless you know what your are doing.
  94. *
  95. * The `true` is returned, that means plugin is done with unsubscription and
  96. * will not be longer polled in future. The default is `false`.
  97. *
  98. */
  99. virtual bool handle_unsubscription(const subscription_point_t &point, bool external) noexcept;
  100. /** \brief remove subscription point from internal storage
  101. *
  102. * If there is no any subscription left, the plugin is deactivated
  103. */
  104. virtual bool forget_subscription(const subscription_point_t &point) noexcept;
  105. /** \brief commits unsubscription via supervisor
  106. *
  107. * Used for foreign subscriptions.
  108. *
  109. */
  110. virtual void forget_subscription(const subscription_info_ptr_t &info) noexcept;
  111. /** \brief invokes the callback if plugin type and phase mach
  112. *
  113. * Upon successful match plugin is casted to the final type, and only then
  114. * passed by reference to the callback. Used in the generic actors plugin
  115. * confuguration to inject custom (per-plugin-type) configuration.
  116. *
  117. */
  118. template <typename Plugin, typename Fn>
  119. void with_casted(Fn &&fn, config_phase_t desired_phase = config_phase_t::INITIALIZING) noexcept {
  120. int phase_match = static_cast<int>(phase) & static_cast<int>(desired_phase);
  121. if (phase_match && identity() == Plugin::class_identity) {
  122. auto &final = static_cast<Plugin &>(*this);
  123. fn(final);
  124. }
  125. }
  126. /** \brief returns the current set of plugin reactions */
  127. std::size_t get_reaction() const noexcept { return reaction; }
  128. /** \brief turns on the specified reaction of the plugin */
  129. void reaction_on(reaction_t value) noexcept { reaction = reaction | value; }
  130. /** \brief turns off the specified reaction of the plugin */
  131. void reaction_off(reaction_t value) noexcept { reaction = reaction & ~value; }
  132. /** \brief generic non-public fields accessor */
  133. template <typename T> auto &access() noexcept;
  134. protected:
  135. /** \brief subscribes plugin to the custom *plugin* handler on the specified address */
  136. template <typename Handler>
  137. subscription_info_ptr_t subscribe(Handler &&handler, const address_ptr_t &address) noexcept;
  138. /** \brief subscribes plugin to the custom *plugin* handler on the main actor address */
  139. template <typename Handler> subscription_info_ptr_t subscribe(Handler &&handler) noexcept;
  140. /** \brief non-owning actor pointer
  141. *
  142. * It is non-null only after plugin activation.
  143. *
  144. */
  145. actor_base_t *actor;
  146. /** \brief makes an error within the context of actor */
  147. extended_error_ptr_t make_error(const std::error_code &ec, const extended_error_ptr_t &next = {}) noexcept;
  148. private:
  149. subscription_container_t own_subscriptions;
  150. std::size_t reaction = 0;
  151. config_phase_t phase = config_phase_t::PREINIT;
  152. };
  153. } // namespace rotor::plugin