supervisor_config.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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 <atomic>
  8. #include "policy.h"
  9. #include "actor_config.h"
  10. #if defined(_MSC_VER)
  11. #pragma warning(push)
  12. #pragma warning(disable : 4251)
  13. #endif
  14. namespace rotor {
  15. /** \struct supervisor_config_t
  16. * \brief base supervisor config, which holds shutdown timeout value
  17. */
  18. struct supervisor_config_t : actor_config_t {
  19. using actor_config_t::actor_config_t;
  20. /** \brief how to behave if child-actor fails */
  21. supervisor_policy_t policy = supervisor_policy_t::shutdown_self;
  22. /** \brief whether the registry actor should be instantiated by supervisor */
  23. bool create_registry = false;
  24. /** \brief whether supervisor should wait until all actors confirmed
  25. * initialization, and only then send start signal to all of them */
  26. bool synchronize_start = false;
  27. /** \brief use the specified address of a registry
  28. *
  29. * Can be useful if an registry was created on the different supervisors
  30. * hierarchy
  31. */
  32. address_ptr_t registry_address;
  33. /** \brief initial queue size for inbound messages. Makes sense only for
  34. * root/leader supervisor */
  35. size_t inbound_queue_size = 64;
  36. /**
  37. * \brief How much time it will spend in polling inbound queue before switching into
  38. * sleep mode (i.e. waiting external messages).
  39. *
  40. * This value might affect I/O latency on event-loops, so set it to zero to
  41. * minimizer I/O latency on event-loops by the rising cross-thread rotor messaging
  42. * latency.
  43. *
  44. */
  45. pt::time_duration poll_duration = pt::millisec{1};
  46. /** \brief pointer to atomic shutdown flag for polling (optional)
  47. *
  48. * When it is set, supervisor will periodically check that the flag
  49. * is set and then shut self down.
  50. *
  51. */
  52. const std::atomic_bool *shutdown_flag = nullptr;
  53. /** \brief the period for checking atomic shutdown flag */
  54. pt::time_duration shutdown_poll_frequency = pt::millisec{100};
  55. };
  56. /** \brief CRTP supervisor config builder */
  57. template <typename Supervisor> struct supervisor_config_builder_t : actor_config_builder_t<Supervisor> {
  58. /** \brief final builder class */
  59. using builder_t = typename Supervisor::template config_builder_t<Supervisor>;
  60. /** \brief parent config builder */
  61. using parent_t = actor_config_builder_t<Supervisor>;
  62. using parent_t::parent_t;
  63. /** \brief defines actor's startup policy */
  64. builder_t &&policy(supervisor_policy_t policy_) &&noexcept {
  65. parent_t::config.policy = policy_;
  66. return std::move(*static_cast<typename parent_t::builder_t *>(this));
  67. }
  68. /** \brief instructs supervisor to create an registry */
  69. builder_t &&create_registry(bool value = true) &&noexcept {
  70. parent_t::config.create_registry = value;
  71. return std::move(*static_cast<typename parent_t::builder_t *>(this));
  72. }
  73. /** \brief instructs supervisor to synchronize start on it's children actors */
  74. builder_t &&synchronize_start(bool value = true) &&noexcept {
  75. parent_t::config.synchronize_start = value;
  76. return std::move(*static_cast<typename parent_t::builder_t *>(this));
  77. }
  78. /** \brief injects external registry address */
  79. builder_t &&registry_address(const address_ptr_t &value) &&noexcept {
  80. parent_t::config.registry_address = value;
  81. return std::move(*static_cast<typename parent_t::builder_t *>(this));
  82. }
  83. /** \brief initial queue size for inbound messages. Makes sense only for
  84. * root/leader supervisor */
  85. builder_t &&inbound_queue_size(size_t value) && {
  86. parent_t::config.inbound_queue_size = value;
  87. return std::move(*static_cast<builder_t *>(this));
  88. }
  89. /** \brief how much time spend in active inbound queue polling */
  90. builder_t &&poll_duration(const pt::time_duration &value) && {
  91. parent_t::config.poll_duration = value;
  92. return std::move(*static_cast<builder_t *>(this));
  93. }
  94. /** \brief atomic shutdown flag and the period for polling it
  95. *
  96. * The thread-safe way to shutdown supervisor even when compiled with
  97. * `BUILD_THREAD_UNSAFE` option. Might be useful in single-threaded
  98. * applications.
  99. *
  100. * For more reactive behavior in thread-safe environment the
  101. * `supervisor::shutdown()` should be used.
  102. *
  103. */
  104. builder_t &&shutdown_flag(const std::atomic_bool &value, const pt::time_duration &interval) && {
  105. parent_t::config.shutdown_flag = &value;
  106. parent_t::config.shutdown_poll_frequency = interval;
  107. return std::move(*static_cast<builder_t *>(this));
  108. }
  109. virtual bool validate() noexcept {
  110. bool r = parent_t::validate();
  111. if (r) {
  112. r = !(parent_t::config.registry_address && parent_t::config.create_registry);
  113. }
  114. return r;
  115. }
  116. };
  117. } // namespace rotor
  118. #if defined(_MSC_VER)
  119. #pragma warning(pop)
  120. #endif