EventHandler.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * Copyright 2014-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <folly/io/async/EventHandler.h>
  17. #include <folly/String.h>
  18. #include <folly/io/async/EventBase.h>
  19. #include <assert.h>
  20. namespace folly {
  21. EventHandler::EventHandler(EventBase* eventBase, int fd) {
  22. folly_event_set(&event_, fd, 0, &EventHandler::libeventCallback, this);
  23. if (eventBase != nullptr) {
  24. setEventBase(eventBase);
  25. } else {
  26. // Callers must set the EventBase and fd before using this timeout.
  27. // Set event_->ev_base to nullptr to ensure that this happens.
  28. // (otherwise libevent will initialize it to the "default" event_base)
  29. event_.ev_base = nullptr;
  30. eventBase_ = nullptr;
  31. }
  32. }
  33. EventHandler::~EventHandler() {
  34. unregisterHandler();
  35. }
  36. bool EventHandler::registerImpl(uint16_t events, bool internal) {
  37. assert(event_.ev_base != nullptr);
  38. // We have to unregister the event before we can change the event flags
  39. if (isHandlerRegistered()) {
  40. // If the new events are the same are the same as the already registered
  41. // flags, we don't have to do anything. Just return.
  42. auto flags = event_ref_flags(&event_);
  43. if (events == event_.ev_events &&
  44. static_cast<bool>(flags & EVLIST_INTERNAL) == internal) {
  45. return true;
  46. }
  47. event_del(&event_);
  48. }
  49. // Update the event flags
  50. // Unfortunately, event_set() resets the event_base, so we have to remember
  51. // it before hand, then pass it back into event_base_set() afterwards
  52. struct event_base* evb = event_.ev_base;
  53. event_set(
  54. &event_,
  55. event_.ev_fd,
  56. short(events),
  57. &EventHandler::libeventCallback,
  58. this);
  59. event_base_set(evb, &event_);
  60. // Set EVLIST_INTERNAL if this is an internal event
  61. if (internal) {
  62. event_ref_flags(&event_) |= EVLIST_INTERNAL;
  63. }
  64. // Add the event.
  65. //
  66. // Although libevent allows events to wait on both I/O and a timeout,
  67. // we intentionally don't allow an EventHandler to also use a timeout.
  68. // Callers must maintain a separate AsyncTimeout object if they want a
  69. // timeout.
  70. //
  71. // Otherwise, it is difficult to handle persistent events properly. (The I/O
  72. // event and timeout may both fire together the same time around the event
  73. // loop. Normally we would want to inform the caller of the I/O event first,
  74. // then the timeout. However, it is difficult to do this properly since the
  75. // I/O callback could delete the EventHandler.) Additionally, if a caller
  76. // uses the same struct event for both I/O and timeout, and they just want to
  77. // reschedule the timeout, libevent currently makes an epoll_ctl() call even
  78. // if the I/O event flags haven't changed. Using a separate event struct is
  79. // therefore slightly more efficient in this case (although it does take up
  80. // more space).
  81. if (event_add(&event_, nullptr) < 0) {
  82. LOG(ERROR) << "EventBase: failed to register event handler for fd "
  83. << event_.ev_fd << ": " << errnoStr(errno);
  84. // Call event_del() to make sure the event is completely uninstalled
  85. event_del(&event_);
  86. return false;
  87. }
  88. return true;
  89. }
  90. void EventHandler::unregisterHandler() {
  91. if (isHandlerRegistered()) {
  92. event_del(&event_);
  93. }
  94. }
  95. void EventHandler::attachEventBase(EventBase* eventBase) {
  96. // attachEventBase() may only be called on detached handlers
  97. assert(event_.ev_base == nullptr);
  98. assert(!isHandlerRegistered());
  99. // This must be invoked from the EventBase's thread
  100. eventBase->dcheckIsInEventBaseThread();
  101. setEventBase(eventBase);
  102. }
  103. void EventHandler::detachEventBase() {
  104. ensureNotRegistered(__func__);
  105. event_.ev_base = nullptr;
  106. }
  107. void EventHandler::changeHandlerFD(int fd) {
  108. ensureNotRegistered(__func__);
  109. // event_set() resets event_base.ev_base, so manually restore it afterwards
  110. struct event_base* evb = event_.ev_base;
  111. folly_event_set(&event_, fd, 0, &EventHandler::libeventCallback, this);
  112. event_.ev_base = evb; // don't use event_base_set(), since evb may be nullptr
  113. }
  114. void EventHandler::initHandler(EventBase* eventBase, int fd) {
  115. ensureNotRegistered(__func__);
  116. folly_event_set(&event_, fd, 0, &EventHandler::libeventCallback, this);
  117. setEventBase(eventBase);
  118. }
  119. void EventHandler::ensureNotRegistered(const char* fn) {
  120. // Neither the EventBase nor file descriptor may be changed while the
  121. // handler is registered. Treat it as a programmer bug and abort the program
  122. // if this requirement is violated.
  123. if (isHandlerRegistered()) {
  124. LOG(ERROR) << fn << " called on registered handler; aborting";
  125. abort();
  126. }
  127. }
  128. void EventHandler::libeventCallback(libevent_fd_t fd, short events, void* arg) {
  129. EventHandler* handler = reinterpret_cast<EventHandler*>(arg);
  130. assert(fd == handler->event_.ev_fd);
  131. (void)fd; // prevent unused variable warnings
  132. auto observer = handler->eventBase_->getExecutionObserver();
  133. if (observer) {
  134. observer->starting(reinterpret_cast<uintptr_t>(handler));
  135. }
  136. // this can't possibly fire if handler->eventBase_ is nullptr
  137. handler->eventBase_->bumpHandlingTime();
  138. handler->handlerReady(uint16_t(events));
  139. if (observer) {
  140. observer->stopped(reinterpret_cast<uintptr_t>(handler));
  141. }
  142. }
  143. void EventHandler::setEventBase(EventBase* eventBase) {
  144. event_base_set(eventBase->getLibeventBase(), &event_);
  145. eventBase_ = eventBase;
  146. }
  147. bool EventHandler::isPending() const {
  148. if (event_ref_flags(&event_) & EVLIST_ACTIVE) {
  149. if (event_.ev_res & EV_READ) {
  150. return true;
  151. }
  152. }
  153. return false;
  154. }
  155. } // namespace folly