Simplified distributed block storage with strong consistency, like in Ceph
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

65 lines
1.6 KiB

  1. // Copyright (c) Vitaliy Filippov, 2019+
  2. // License: VNPL-1.0 or GNU GPL-2.0+ (see README.md for details)
  3. #include <sys/timerfd.h>
  4. #include <sys/poll.h>
  5. #include <unistd.h>
  6. #include "timerfd_interval.h"
  7. timerfd_interval::timerfd_interval(ring_loop_t *ringloop, int seconds, std::function<void(void)> cb)
  8. {
  9. wait_state = 0;
  10. timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
  11. if (timerfd < 0)
  12. {
  13. throw std::runtime_error(std::string("timerfd_create: ") + strerror(errno));
  14. }
  15. struct itimerspec exp = {
  16. .it_interval = { seconds, 0 },
  17. .it_value = { seconds, 0 },
  18. };
  19. if (timerfd_settime(timerfd, 0, &exp, NULL))
  20. {
  21. throw std::runtime_error(std::string("timerfd_settime: ") + strerror(errno));
  22. }
  23. consumer.loop = [this]() { loop(); };
  24. ringloop->register_consumer(&consumer);
  25. this->ringloop = ringloop;
  26. this->callback = cb;
  27. }
  28. timerfd_interval::~timerfd_interval()
  29. {
  30. ringloop->unregister_consumer(&consumer);
  31. close(timerfd);
  32. }
  33. void timerfd_interval::loop()
  34. {
  35. if (wait_state == 1)
  36. {
  37. return;
  38. }
  39. struct io_uring_sqe *sqe = ringloop->get_sqe();
  40. if (!sqe)
  41. {
  42. wait_state = 0;
  43. return;
  44. }
  45. struct ring_data_t *data = ((ring_data_t*)sqe->user_data);
  46. my_uring_prep_poll_add(sqe, timerfd, POLLIN);
  47. data->callback = [&](ring_data_t *data)
  48. {
  49. if (data->res < 0)
  50. {
  51. throw std::runtime_error(std::string("waiting for timer failed: ") + strerror(-data->res));
  52. }
  53. uint64_t n;
  54. read(timerfd, &n, 8);
  55. wait_state = 0;
  56. callback();
  57. };
  58. wait_state = 1;
  59. ringloop->submit();
  60. }