actor_config.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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 <deque>
  8. #include <tuple>
  9. #include <functional>
  10. #include <memory>
  11. #include "arc.hpp"
  12. #include "plugins.h"
  13. #include "policy.h"
  14. #include "forward.hpp"
  15. #if defined(_MSC_VER)
  16. #pragma warning(push)
  17. #pragma warning(disable : 4251)
  18. #endif
  19. namespace rotor {
  20. /** \brief list of raw plugin pointers*/
  21. using plugins_t = std::deque<plugin::plugin_base_t *>;
  22. /** \struct plugin_storage_base_t
  23. * \brief abstract item to store plugins inside actor */
  24. struct plugin_storage_base_t {
  25. virtual ~plugin_storage_base_t() {}
  26. /** \brief returns list of plugins pointers from the storage */
  27. virtual plugins_t get_plugins() noexcept = 0;
  28. };
  29. /** \brief smart pointer for {@link plugin_storage_base_t} */
  30. using plugin_storage_ptr_t = std::unique_ptr<plugin_storage_base_t>;
  31. /** \brief templated plugin storage implementation */
  32. template <typename PluginList> struct plugin_storage_t : plugin_storage_base_t {
  33. plugins_t get_plugins() noexcept override {
  34. plugins_t plugins;
  35. add_plugin(plugins);
  36. return plugins;
  37. }
  38. private:
  39. PluginList plugin_list;
  40. template <size_t Index = 0> void add_plugin(plugins_t &plugins) noexcept {
  41. plugins.emplace_back(&std::get<Index>(plugin_list));
  42. if constexpr (Index + 1 < std::tuple_size_v<PluginList>) {
  43. add_plugin<Index + 1>(plugins);
  44. }
  45. }
  46. };
  47. /** \struct actor_config_t
  48. * \brief basic actor configuration: init and shutdown timeouts, etc.
  49. */
  50. struct actor_config_t {
  51. /** \brief constructs {@link plugin_storage_ptr_t} (type) */
  52. using plugins_constructor_t = std::function<plugin_storage_ptr_t()>;
  53. /** \brief constructs {@link plugin_storage_ptr_t} */
  54. plugins_constructor_t plugins_constructor;
  55. /** \brief raw pointer to {@link supervisor_t} */
  56. supervisor_t *supervisor;
  57. /** \brief max actor initialization time */
  58. pt::time_duration init_timeout;
  59. /** \brief max actor shutdown time */
  60. pt::time_duration shutdown_timeout;
  61. /** \brief address of the spawner */
  62. address_ptr_t spawner_address;
  63. /** \brief shutdown supervisor upon child failure */
  64. bool escalate_failure = false;
  65. /** \brief shutdown supervisor upon child down */
  66. bool autoshutdown_supervisor = false;
  67. /** \brief constructs actor_config_t from raw supervisor pointer */
  68. actor_config_t(supervisor_t *supervisor_) : supervisor{supervisor_} {}
  69. };
  70. /** \brief CRTP actor config builder */
  71. template <typename Actor> struct actor_config_builder_t {
  72. /** \brief final builder class */
  73. using builder_t = typename Actor::template config_builder_t<Actor>;
  74. /** \brief final config class */
  75. using config_t = typename Actor::config_t;
  76. /** \brief intrusive pointer to actor */
  77. using actor_ptr_t = intrusive_ptr_t<Actor>;
  78. /** \brief actor post-constructor callback type
  79. *
  80. * For example, supervisor on_init() is invoked early (right after instantiation)
  81. *
  82. */
  83. using install_action_t = std::function<void(actor_ptr_t &)>;
  84. /** \brief bit mask for init timeout validation */
  85. constexpr static const std::uint32_t INIT_TIMEOUT = 1 << 0;
  86. /** \brief bit mask for shutdown timeout validation */
  87. constexpr static const std::uint32_t SHUTDOWN_TIMEOUT = 1 << 1;
  88. /** \brief bit mask for all required fields */
  89. constexpr static const std::uint32_t requirements_mask = INIT_TIMEOUT | SHUTDOWN_TIMEOUT;
  90. /** \brief post-construction callback */
  91. install_action_t install_action;
  92. /** \brief raw pointer to `supervisor_t` (is `null` for top-level supervisors) */
  93. supervisor_t *supervisor;
  94. /** \brief reference to `system_context_t` */
  95. system_context_t &system_context;
  96. /** \brief the currently build config */
  97. config_t config;
  98. /** \brief required fields mask (used for validation) */
  99. std::uint32_t mask = builder_t::requirements_mask;
  100. /** \brief ctor with install action and raw pointer to supervisor */
  101. actor_config_builder_t(install_action_t &&action_, supervisor_t *supervisor_);
  102. /** \brief ctor with install action and pointer to `system_context_t` */
  103. actor_config_builder_t(install_action_t &&action_, system_context_t &system_context_)
  104. : install_action{std::move(action_)}, supervisor{nullptr}, system_context{system_context_}, config{nullptr} {
  105. init_ctor();
  106. }
  107. /** \brief setter for init and shutdown timeout */
  108. builder_t &&timeout(const pt::time_duration &timeout) && noexcept {
  109. config.init_timeout = config.shutdown_timeout = timeout;
  110. mask = (mask & (~INIT_TIMEOUT & ~SHUTDOWN_TIMEOUT));
  111. return std::move(*static_cast<builder_t *>(this));
  112. }
  113. /** \brief setter for init timeout */
  114. builder_t &&init_timeout(const pt::time_duration &timeout) && noexcept {
  115. config.init_timeout = timeout;
  116. mask = (mask & ~INIT_TIMEOUT);
  117. return std::move(*static_cast<builder_t *>(this));
  118. }
  119. /** \brief setter for shutdown timeout */
  120. builder_t &&shutdown_timeout(const pt::time_duration &timeout) && noexcept {
  121. config.shutdown_timeout = timeout;
  122. mask = (mask & ~SHUTDOWN_TIMEOUT);
  123. return std::move(*static_cast<builder_t *>(this));
  124. }
  125. /** \brief spawner address
  126. *
  127. * This value must be set, when actor is create via spawner (i.e. in `factory_t`)
  128. *
  129. **/
  130. builder_t &&spawner_address(const address_ptr_t &value) && noexcept {
  131. config.spawner_address = value;
  132. return std::move(*static_cast<builder_t *>(this));
  133. }
  134. /** \brief shutdown supervisor upon actor failure
  135. *
  136. * When actor is shut down due to failure, trigger it's supervisor
  137. * to shutdown.
  138. *
  139. * This policy is ignored when actor is spawned.
  140. *
  141. */
  142. builder_t &&escalate_failure(bool value = true) && noexcept {
  143. config.escalate_failure = value;
  144. return std::move(*static_cast<builder_t *>(this));
  145. }
  146. /** \brief shutdown supervisor when an actor is down
  147. *
  148. * This policy is ignored when actor is spawned.
  149. *
  150. */
  151. builder_t &&autoshutdown_supervisor(bool value = true) && noexcept {
  152. config.autoshutdown_supervisor = value;
  153. return std::move(*static_cast<builder_t *>(this));
  154. }
  155. /** \brief checks whether config is valid, i.e. all necessary fields are set */
  156. virtual bool validate() noexcept { return mask ? false : true; }
  157. /** \brief constructs actor from the current config */
  158. actor_ptr_t finish() &&;
  159. virtual ~actor_config_builder_t() = default;
  160. private:
  161. void init_ctor() noexcept {
  162. config.plugins_constructor = []() -> plugin_storage_ptr_t {
  163. using plugins_list_t = typename Actor::plugins_list_t;
  164. using storage_t = plugin_storage_t<plugins_list_t>;
  165. return std::make_unique<storage_t>();
  166. };
  167. }
  168. };
  169. } // namespace rotor
  170. #if defined(_MSC_VER)
  171. #pragma warning(pop)
  172. #endif