poll_interrupter.h 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #pragma once
  2. #include <util/system/defaults.h>
  3. #include <util/generic/yexception.h>
  4. #include <util/network/socket.h>
  5. #include <util/system/pipe.h>
  6. #ifdef _linux_
  7. #include <sys/eventfd.h>
  8. #endif
  9. #if defined(_bionic_) && !defined(EFD_SEMAPHORE)
  10. #define EFD_SEMAPHORE 1
  11. #endif
  12. namespace NAsio {
  13. #ifdef _linux_
  14. class TEventFdPollInterrupter {
  15. public:
  16. inline TEventFdPollInterrupter() {
  17. F_ = eventfd(0, EFD_NONBLOCK | EFD_SEMAPHORE);
  18. if (F_ < 0) {
  19. ythrow TFileError() << "failed to create a eventfd";
  20. }
  21. }
  22. inline ~TEventFdPollInterrupter() {
  23. close(F_);
  24. }
  25. inline void Interrupt() const noexcept {
  26. const static eventfd_t ev(1);
  27. ssize_t res = ::write(F_, &ev, sizeof ev);
  28. Y_UNUSED(res);
  29. }
  30. inline bool Reset() const noexcept {
  31. eventfd_t ev(0);
  32. for (;;) {
  33. ssize_t res = ::read(F_, &ev, sizeof ev);
  34. if (res && res == EINTR) {
  35. continue;
  36. }
  37. return res > 0;
  38. }
  39. }
  40. int Fd() {
  41. return F_;
  42. }
  43. private:
  44. int F_;
  45. };
  46. #endif
  47. class TPipePollInterrupter {
  48. public:
  49. TPipePollInterrupter() {
  50. TPipeHandle::Pipe(S_[0], S_[1]);
  51. SetNonBlock(S_[0]);
  52. SetNonBlock(S_[1]);
  53. }
  54. inline void Interrupt() const noexcept {
  55. char byte = 0;
  56. ssize_t res = S_[1].Write(&byte, 1);
  57. Y_UNUSED(res);
  58. }
  59. inline bool Reset() const noexcept {
  60. char buff[256];
  61. for (;;) {
  62. ssize_t r = S_[0].Read(buff, sizeof buff);
  63. if (r < 0 && r == EINTR) {
  64. continue;
  65. }
  66. bool wasInterrupted = r > 0;
  67. while (r == sizeof buff) {
  68. r = S_[0].Read(buff, sizeof buff);
  69. }
  70. return wasInterrupted;
  71. }
  72. }
  73. PIPEHANDLE Fd() const noexcept {
  74. return S_[0];
  75. }
  76. private:
  77. TPipeHandle S_[2];
  78. };
  79. #ifdef _linux_
  80. typedef TEventFdPollInterrupter TPollInterrupter; //more effective than pipe, but only linux impl.
  81. #else
  82. typedef TPipePollInterrupter TPollInterrupter;
  83. #endif
  84. }