supervisor_ev.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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/supervisor.h"
  8. #include "rotor/ev/export.h"
  9. #include "rotor/ev/supervisor_config_ev.h"
  10. #include "rotor/ev/system_context_ev.h"
  11. #include "rotor/system_context.h"
  12. #include <ev.h>
  13. #include <memory>
  14. #include <unordered_map>
  15. namespace rotor {
  16. namespace ev {
  17. /** \struct supervisor_ev_t
  18. * \brief delivers rotor-messages on top of libev event loop
  19. *
  20. * Basically it uses libev `ev_async` watcher to deliver `rotor` messages
  21. * on top of ev event loop.
  22. *
  23. * Since ev event loop is not thread-safe and do not provide different
  24. * execution context (theads), creating sub-supervisors (non-root) will
  25. * not bring concurrency advantages. It is possible, however, create
  26. * different event loops and let them be used by different threads;
  27. * in that case different supervisors, and they will be able to communicate
  28. * via rotor-messaging.
  29. *
  30. */
  31. struct ROTOR_EV_API supervisor_ev_t : public supervisor_t {
  32. /** \brief injects an alias for supervisor_config_ev_t */
  33. using config_t = supervisor_config_ev_t;
  34. /** \brief injects templated supervisor_config_ev_builder_t */
  35. template <typename Supervisor> using config_builder_t = supervisor_config_ev_builder_t<Supervisor>;
  36. /** \struct timer_t
  37. * \brief inheritance of ev_timer, which holds rotor `timer_id`
  38. */
  39. struct timer_t : public ev_timer {
  40. /** \brief intrusive pointer to ev supervistor (type) */
  41. using supervisor_ptr_t = intrusive_ptr_t<supervisor_ev_t>;
  42. /** \brief non-owning pointer to timer handler */
  43. timer_handler_base_t *handler;
  44. /** \brief intrusive pointer to the supervisor */
  45. supervisor_ptr_t sup;
  46. };
  47. /** \brief an alias for unique pointer, holding `timer_t` */
  48. using timer_ptr_t = std::unique_ptr<timer_t>;
  49. /** \brief constructs new supervisor from ev supervisor config */
  50. supervisor_ev_t(supervisor_config_ev_t &config);
  51. virtual void do_initialize(system_context_t *ctx) noexcept override;
  52. ~supervisor_ev_t();
  53. void start() noexcept override;
  54. void shutdown() noexcept override;
  55. void enqueue(message_ptr_t message) noexcept override;
  56. void shutdown_finish() noexcept override;
  57. /** \brief retuns ev-loop associated with the supervisor */
  58. inline struct ev_loop *get_loop() noexcept { return loop; }
  59. /** \brief returns pointer to the ev system context */
  60. inline system_context_ev_t *get_context() noexcept { return static_cast<system_context_ev_t *>(context); }
  61. /** \brief generic non-public fields accessor */
  62. template <typename T> auto &access() noexcept;
  63. protected:
  64. /** \brief a type for mapping `timer_id` to timer pointer */
  65. using timers_map_t = std::unordered_map<request_id_t, timer_ptr_t>;
  66. /** \brief EV-specific trampoline function for `on_async` method */
  67. static void async_cb(EV_P_ ev_async *w, int revents) noexcept;
  68. void do_start_timer(const pt::time_duration &interval, timer_handler_base_t &handler) noexcept override;
  69. void do_cancel_timer(request_id_t timer_id) noexcept override;
  70. /** \brief Process external messages (from inbound queue).
  71. *
  72. * Used for moving messages in a thread-safe way for the supervisor
  73. * from external (inbound) queue into internal queue and do further
  74. * processing / delivery of the messages.
  75. *
  76. */
  77. virtual void on_async() noexcept;
  78. /** \brief a pointer to EV event loop, copied from config */
  79. struct ev_loop *loop;
  80. /** \brief whether loop should be destroyed by supervisor, copied from config */
  81. bool loop_ownership;
  82. /** \brief ev-loop specific thread-safe wake-up notifier for external messages delivery */
  83. ev_async async_watcher;
  84. /** \brief how much time spend in active inbound queue polling */
  85. ev_tstamp poll_duration;
  86. /** \brief timer_id to timer map */
  87. timers_map_t timers_map;
  88. friend struct supervisor_ev_shutdown_t;
  89. private:
  90. void move_inbound_queue() noexcept;
  91. };
  92. } // namespace ev
  93. } // namespace rotor