supervisor_ev.h 4.0 KB

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