ping-pong-fltk.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include <rotor/fltk.hpp>
  2. #include <FL/Fl.H>
  3. #include <FL/Fl_Window.H>
  4. #include <FL/Fl_Box.H>
  5. #ifndef _WIN32
  6. #include <X11/Xlib.h>
  7. #include <cstdlib>
  8. #endif
  9. namespace r = rotor;
  10. namespace rf = r::fltk;
  11. namespace payload {
  12. struct ping_t {};
  13. struct pong_t {};
  14. } // namespace payload
  15. namespace message {
  16. using ping_t = r::message_t<payload::ping_t>;
  17. using pong_t = r::message_t<payload::pong_t>;
  18. } // namespace message
  19. struct pinger_t : public r::actor_base_t {
  20. using rotor::actor_base_t::actor_base_t;
  21. void configure(r::plugin::plugin_base_t &plugin) noexcept override {
  22. r::actor_base_t::configure(plugin);
  23. plugin.with_casted<r::plugin::starter_plugin_t>([](auto &p) { p.subscribe_actor(&pinger_t::on_pong); });
  24. }
  25. void on_start() noexcept override {
  26. r::actor_base_t::on_start();
  27. auto timeout = r::pt::seconds{2};
  28. start_timer(timeout, *this, &pinger_t::on_ping_timer);
  29. }
  30. void on_ping_timer(r::request_id_t, bool) noexcept {
  31. box->label("ping has been sent");
  32. send<payload::ping_t>(ponger_addr);
  33. }
  34. void on_pong(message::pong_t &) noexcept {
  35. box->label("pong has been received, going to shutdown");
  36. auto timeout = r::pt::seconds{1};
  37. start_timer(timeout, *this, &pinger_t::on_shutdown_timer);
  38. }
  39. void on_shutdown_timer(r::request_id_t, bool) noexcept { supervisor->shutdown(); }
  40. rotor::address_ptr_t ponger_addr;
  41. Fl_Box *box;
  42. };
  43. struct ponger_t : r::actor_base_t {
  44. using rotor::actor_base_t::actor_base_t;
  45. void configure(r::plugin::plugin_base_t &plugin) noexcept override {
  46. r::actor_base_t::configure(plugin);
  47. plugin.with_casted<r::plugin::starter_plugin_t>([](auto &p) { p.subscribe_actor(&ponger_t::on_ping); });
  48. }
  49. void on_ping(message::ping_t &) noexcept {
  50. auto timeout = r::pt::seconds{2};
  51. start_timer(timeout, *this, &ponger_t::on_timer);
  52. }
  53. void on_timer(r::request_id_t, bool) noexcept { send<payload::pong_t>(pinger_addr); }
  54. rotor::address_ptr_t pinger_addr;
  55. };
  56. bool is_display_available() {
  57. #ifndef _WIN32
  58. char *disp = getenv("DISPLAY");
  59. if (disp == nullptr)
  60. return false;
  61. Display *dpy = XOpenDisplay(disp);
  62. if (dpy == nullptr)
  63. return false;
  64. XCloseDisplay(dpy);
  65. #endif
  66. return true;
  67. }
  68. int main(int argc, char **argv) {
  69. if (!is_display_available()) {
  70. return 0;
  71. }
  72. // let fltk-core be aware of lockin mechanism (i.e. Fl::awake will work)
  73. Fl::lock();
  74. Fl_Window window = Fl_Window(400, 180);
  75. Fl_Box *box = new Fl_Box(20, 40, 360, 100, "auto shutdown in 5 seconds");
  76. box->box(FL_UP_BOX);
  77. window.end();
  78. window.show(argc, argv);
  79. auto system_context = rf::system_context_fltk_t();
  80. auto timeout = r::pt::millisec{250};
  81. auto supervisor =
  82. system_context.create_supervisor<rf::supervisor_fltk_t>().timeout(timeout).create_registry().finish();
  83. auto pinger = supervisor->create_actor<pinger_t>().timeout(timeout).finish();
  84. auto ponger = supervisor->create_actor<ponger_t>().timeout(timeout).finish();
  85. pinger->box = box;
  86. pinger->ponger_addr = ponger->get_address();
  87. ponger->pinger_addr = pinger->get_address();
  88. supervisor->start();
  89. while (!supervisor->get_shutdown_reason()) {
  90. supervisor->do_process();
  91. Fl::wait(0.1);
  92. }
  93. return 0;
  94. }