proxygen
folly::EventHandler Class Referenceabstract

#include <EventHandler.h>

Inheritance diagram for folly::EventHandler:
EventHandlerMock fizz::tool::TerminalInputHandler folly::AsyncPipeReader folly::AsyncPipeWriter folly::AsyncServerSocket::ServerEventHandler folly::AsyncSocket::IoHandler folly::AsyncUDPSocket folly::NotificationQueue< MessageT >::Consumer PipeHandler TerminateTestCallback TestHandler

Public Types

enum  EventFlags {
  NONE = 0, READ = EV_READ, WRITE = EV_WRITE, READ_WRITE = (READ | WRITE),
  PERSIST = EV_PERSIST
}
 

Public Member Functions

 EventHandler (EventBase *eventBase, int fd)
 
 EventHandler (EventBase *eventBase=nullptr, NetworkSocket fd=NetworkSocket())
 
virtual ~EventHandler ()
 
virtual void handlerReady (uint16_t events) noexcept=0
 
bool registerHandler (uint16_t events)
 
void unregisterHandler ()
 
bool isHandlerRegistered () const
 
void attachEventBase (EventBase *eventBase)
 
void detachEventBase ()
 
void changeHandlerFD (int fd)
 
void changeHandlerFD (NetworkSocket fd)
 
void initHandler (EventBase *eventBase, int fd)
 
void initHandler (EventBase *eventBase, NetworkSocket fd)
 
uint16_t getRegisteredEvents () const
 
bool registerInternalHandler (uint16_t events)
 
bool isPending () const
 

Private Member Functions

bool registerImpl (uint16_t events, bool internal)
 
void ensureNotRegistered (const char *fn)
 
void setEventBase (EventBase *eventBase)
 

Static Private Member Functions

static void libeventCallback (libevent_fd_t fd, short events, void *arg)
 

Private Attributes

struct event event_
 
EventBaseeventBase_
 

Detailed Description

The EventHandler class is used to asynchronously wait for events on a file descriptor.

Users that wish to wait on I/O events should derive from EventHandler and implement the handlerReady() method.

Definition at line 39 of file EventHandler.h.

Member Enumeration Documentation

Enumerator
NONE 
READ 
WRITE 
READ_WRITE 
PERSIST 

Definition at line 41 of file EventHandler.h.

41  {
42  NONE = 0,
43  READ = EV_READ,
44  WRITE = EV_WRITE,
45  READ_WRITE = (READ | WRITE),
46  PERSIST = EV_PERSIST,
47 // Temporary flag until EPOLLPRI is upstream on libevent.
48 #ifdef EV_PRI
49  PRI = EV_PRI,
50 #endif
51  };

Constructor & Destructor Documentation

folly::EventHandler::EventHandler ( EventBase eventBase,
int  fd 
)
inlineexplicit

Create a new EventHandler object.

Parameters
eventBaseThe EventBase to use to drive this event handler. This may be nullptr, in which case the EventBase must be set separately using initHandler() or attachEventBase() before the handler can be registered.
fdThe file descriptor that this EventHandler will monitor. This may be -1, in which case the file descriptor must be set separately using initHandler() or changeHandlerFD() before the handler can be registered.

Definition at line 65 of file EventHandler.h.

References handlerReady(), folly::pushmi::__adl::noexcept(), uint16_t, and ~EventHandler().

66  : EventHandler(eventBase, NetworkSocket::fromFd(fd)) {}
EventHandler(EventBase *eventBase, int fd)
Definition: EventHandler.h:65
static NetworkSocket fromFd(int fd)
Definition: NetworkSocket.h:44
folly::EventHandler::EventHandler ( EventBase eventBase = nullptr,
NetworkSocket  fd = NetworkSocket() 
)
explicit

Definition at line 25 of file EventHandler.cpp.

References event_, eventBase_, folly::folly_event_set(), libeventCallback(), setEventBase(), and folly::NetworkSocket::toFd().

25  {
27  if (eventBase != nullptr) {
28  setEventBase(eventBase);
29  } else {
30  // Callers must set the EventBase and fd before using this timeout.
31  // Set event_->ev_base to nullptr to ensure that this happens.
32  // (otherwise libevent will initialize it to the "default" event_base)
33  event_.ev_base = nullptr;
34  eventBase_ = nullptr;
35  }
36 }
struct event event_
Definition: EventHandler.h:197
static void libeventCallback(libevent_fd_t fd, short events, void *arg)
void setEventBase(EventBase *eventBase)
void folly_event_set(event *e, int fd, short s, EventSetCallback f, void *arg)
Definition: Event.h:50
EventBase * eventBase_
Definition: EventHandler.h:198
folly::EventHandler::~EventHandler ( )
virtual

EventHandler destructor.

The event will be automatically unregistered if it is still registered.

Definition at line 38 of file EventHandler.cpp.

References unregisterHandler().

Referenced by EventHandler().

38  {
40 }

Member Function Documentation

void folly::EventHandler::attachEventBase ( EventBase eventBase)

Attach the handler to a EventBase.

This may only be called if the handler is not currently attached to a EventBase (either by using the default constructor, or by calling detachEventBase()).

This method must be invoked in the EventBase's thread.

Definition at line 109 of file EventHandler.cpp.

References folly::EventBase::dcheckIsInEventBaseThread(), event_, isHandlerRegistered(), and setEventBase().

Referenced by folly::AsyncUDPSocket::attachEventBase(), folly::AsyncSocket::attachEventBase(), and isHandlerRegistered().

109  {
110  // attachEventBase() may only be called on detached handlers
111  assert(event_.ev_base == nullptr);
112  assert(!isHandlerRegistered());
113  // This must be invoked from the EventBase's thread
114  eventBase->dcheckIsInEventBaseThread();
115 
116  setEventBase(eventBase);
117 }
struct event event_
Definition: EventHandler.h:197
void setEventBase(EventBase *eventBase)
bool isHandlerRegistered() const
Definition: EventHandler.h:112
void folly::EventHandler::changeHandlerFD ( int  fd)
inline

Change the file descriptor that this handler is associated with.

This may only be called when the handler is not currently registered.

Definition at line 143 of file EventHandler.h.

References folly::NetworkSocket::fromFd().

Referenced by folly::AsyncUDPSocket::bind(), folly::AsyncPipeReader::close(), folly::AsyncPipeWriter::closeNow(), folly::AsyncSocket::closeNow(), folly::AsyncSocket::connect(), folly::AsyncSocket::detachFd(), folly::AsyncSocket::handleWrite(), folly::AsyncUDPSocket::setFD(), and folly::AsyncSocket::startFail().

143  {
145  }
void changeHandlerFD(int fd)
Definition: EventHandler.h:143
static NetworkSocket fromFd(int fd)
Definition: NetworkSocket.h:44
void folly::EventHandler::changeHandlerFD ( NetworkSocket  fd)

Definition at line 124 of file EventHandler.cpp.

References ensureNotRegistered(), event_, folly::folly_event_set(), libeventCallback(), and folly::NetworkSocket::toFd().

124  {
125  ensureNotRegistered(__func__);
126  // event_set() resets event_base.ev_base, so manually restore it afterwards
127  struct event_base* evb = event_.ev_base;
128  folly_event_set(&event_, fd.toFd(), 0, &EventHandler::libeventCallback, this);
129  event_.ev_base = evb; // don't use event_base_set(), since evb may be nullptr
130 }
struct event event_
Definition: EventHandler.h:197
static void libeventCallback(libevent_fd_t fd, short events, void *arg)
void folly_event_set(event *e, int fd, short s, EventSetCallback f, void *arg)
Definition: Event.h:50
void ensureNotRegistered(const char *fn)
void folly::EventHandler::detachEventBase ( )

Detach the handler from its EventBase.

This may only be called when the handler is not currently registered. Once detached, the handler may not be registered again until it is re-attached to a EventBase by calling attachEventBase().

This method must be called from the current EventBase's thread.

Definition at line 119 of file EventHandler.cpp.

References ensureNotRegistered(), and event_.

Referenced by folly::AsyncUDPSocket::detachEventBase(), folly::AsyncSocket::detachEventBase(), and isHandlerRegistered().

119  {
120  ensureNotRegistered(__func__);
121  event_.ev_base = nullptr;
122 }
struct event event_
Definition: EventHandler.h:197
void ensureNotRegistered(const char *fn)
void folly::EventHandler::ensureNotRegistered ( const char *  fn)
private

Definition at line 138 of file EventHandler.cpp.

References isHandlerRegistered().

Referenced by changeHandlerFD(), detachEventBase(), initHandler(), and registerInternalHandler().

138  {
139  // Neither the EventBase nor file descriptor may be changed while the
140  // handler is registered. Treat it as a programmer bug and abort the program
141  // if this requirement is violated.
142  if (isHandlerRegistered()) {
143  LOG(ERROR) << fn << " called on registered handler; aborting";
144  abort();
145  }
146 }
bool isHandlerRegistered() const
Definition: EventHandler.h:112
uint16_t folly::EventHandler::getRegisteredEvents ( ) const
inline

Return the set of events that we're currently registered for.

Definition at line 165 of file EventHandler.h.

References event_, isHandlerRegistered(), and uint16_t.

165  {
166  return (isHandlerRegistered()) ? uint16_t(event_.ev_events) : 0u;
167  }
struct event event_
Definition: EventHandler.h:197
bool isHandlerRegistered() const
Definition: EventHandler.h:112
virtual void folly::EventHandler::handlerReady ( uint16_t  events)
pure virtualnoexcept
void folly::EventHandler::initHandler ( EventBase eventBase,
int  fd 
)
inline

Attach the handler to a EventBase, and change the file descriptor.

This method may only be called if the handler is not currently attached to a EventBase. This is primarily intended to be used to initialize EventHandler objects created using the default constructor.

Definition at line 156 of file EventHandler.h.

References folly::NetworkSocket::fromFd().

156  {
157  initHandler(eventBase, NetworkSocket::fromFd(fd));
158  }
void initHandler(EventBase *eventBase, int fd)
Definition: EventHandler.h:156
static NetworkSocket fromFd(int fd)
Definition: NetworkSocket.h:44
void folly::EventHandler::initHandler ( EventBase eventBase,
NetworkSocket  fd 
)

Definition at line 132 of file EventHandler.cpp.

References ensureNotRegistered(), event_, folly::folly_event_set(), libeventCallback(), setEventBase(), and folly::NetworkSocket::toFd().

132  {
133  ensureNotRegistered(__func__);
134  folly_event_set(&event_, fd.toFd(), 0, &EventHandler::libeventCallback, this);
135  setEventBase(eventBase);
136 }
struct event event_
Definition: EventHandler.h:197
static void libeventCallback(libevent_fd_t fd, short events, void *arg)
void setEventBase(EventBase *eventBase)
void folly_event_set(event *e, int fd, short s, EventSetCallback f, void *arg)
Definition: Event.h:50
void ensureNotRegistered(const char *fn)
bool folly::EventHandler::isHandlerRegistered ( ) const
inline
bool folly::EventHandler::isPending ( ) const

Definition at line 173 of file EventHandler.cpp.

References event_, and folly::event_ref_flags().

Referenced by folly::AsyncSocket::isPending(), and registerInternalHandler().

173  {
174  if (event_ref_flags(&event_) & EVLIST_ACTIVE) {
175  if (event_.ev_res & EV_READ) {
176  return true;
177  }
178  }
179  return false;
180 }
struct event event_
Definition: EventHandler.h:197
auto event_ref_flags(struct event *ev) -> decltype(std::ref(ev->ev_flags))
Definition: EventUtil.h:41
void folly::EventHandler::libeventCallback ( libevent_fd_t  fd,
short  events,
void *  arg 
)
staticprivate

Definition at line 148 of file EventHandler.cpp.

References folly::EventBase::bumpHandlingTime(), event_, eventBase_, folly::EventBase::getExecutionObserver(), handler(), handlerReady(), folly::ExecutionObserver::starting(), and uint16_t.

Referenced by changeHandlerFD(), EventHandler(), initHandler(), registerImpl(), and registerInternalHandler().

148  {
149  EventHandler* handler = reinterpret_cast<EventHandler*>(arg);
150  assert(fd == handler->event_.ev_fd);
151  (void)fd; // prevent unused variable warnings
152 
153  auto observer = handler->eventBase_->getExecutionObserver();
154  if (observer) {
155  observer->starting(reinterpret_cast<uintptr_t>(handler));
156  }
157 
158  // this can't possibly fire if handler->eventBase_ is nullptr
159  handler->eventBase_->bumpHandlingTime();
160 
161  handler->handlerReady(uint16_t(events));
162 
163  if (observer) {
164  observer->stopped(reinterpret_cast<uintptr_t>(handler));
165  }
166 }
void handler(int, siginfo_t *, void *)
EventHandler(EventBase *eventBase, int fd)
Definition: EventHandler.h:65
bool folly::EventHandler::registerHandler ( uint16_t  events)
inline

Register the handler.

If the handler is already registered, the registration will be updated to wait on the new set of events.

Parameters
eventsA bitset specifying the events to monitor. If the PERSIST bit is set, the handler will remain registered even after handlerReady() is called.
Returns
Returns true if the handler was successfully registered, or false if an error occurred. After an error, the handler is always unregistered, even if it was already registered prior to this call to registerHandler().

Definition at line 100 of file EventHandler.h.

References registerImpl(), and unregisterHandler().

Referenced by folly::AsyncUDPSocket::detachEventBase(), folly::AsyncPipeWriter::handleWrite(), folly::AsyncSocket::registerForConnectEvents(), folly::AsyncPipeReader::setReadCB(), fizz::tool::TerminalInputHandler::TerminalInputHandler(), TEST(), TEST_F(), folly::AsyncSocket::updateEventRegistration(), and folly::AsyncUDPSocket::updateRegistration().

100  {
101  return registerImpl(events, false);
102  }
bool registerImpl(uint16_t events, bool internal)
bool folly::EventHandler::registerImpl ( uint16_t  events,
bool  internal 
)
private

Definition at line 42 of file EventHandler.cpp.

References folly::errnoStr(), event_, folly::event_ref_flags(), isHandlerRegistered(), and libeventCallback().

Referenced by registerHandler(), and registerInternalHandler().

42  {
43  assert(event_.ev_base != nullptr);
44 
45  // We have to unregister the event before we can change the event flags
46  if (isHandlerRegistered()) {
47  // If the new events are the same are the same as the already registered
48  // flags, we don't have to do anything. Just return.
49  auto flags = event_ref_flags(&event_);
50  if (events == event_.ev_events &&
51  static_cast<bool>(flags & EVLIST_INTERNAL) == internal) {
52  return true;
53  }
54 
55  event_del(&event_);
56  }
57 
58  // Update the event flags
59  // Unfortunately, event_set() resets the event_base, so we have to remember
60  // it before hand, then pass it back into event_base_set() afterwards
61  struct event_base* evb = event_.ev_base;
62  event_set(
63  &event_,
64  event_.ev_fd,
65  short(events),
67  this);
68  event_base_set(evb, &event_);
69 
70  // Set EVLIST_INTERNAL if this is an internal event
71  if (internal) {
72  event_ref_flags(&event_) |= EVLIST_INTERNAL;
73  }
74 
75  // Add the event.
76  //
77  // Although libevent allows events to wait on both I/O and a timeout,
78  // we intentionally don't allow an EventHandler to also use a timeout.
79  // Callers must maintain a separate AsyncTimeout object if they want a
80  // timeout.
81  //
82  // Otherwise, it is difficult to handle persistent events properly. (The I/O
83  // event and timeout may both fire together the same time around the event
84  // loop. Normally we would want to inform the caller of the I/O event first,
85  // then the timeout. However, it is difficult to do this properly since the
86  // I/O callback could delete the EventHandler.) Additionally, if a caller
87  // uses the same struct event for both I/O and timeout, and they just want to
88  // reschedule the timeout, libevent currently makes an epoll_ctl() call even
89  // if the I/O event flags haven't changed. Using a separate event struct is
90  // therefore slightly more efficient in this case (although it does take up
91  // more space).
92  if (event_add(&event_, nullptr) < 0) {
93  LOG(ERROR) << "EventBase: failed to register event handler for fd "
94  << event_.ev_fd << ": " << errnoStr(errno);
95  // Call event_del() to make sure the event is completely uninstalled
96  event_del(&event_);
97  return false;
98  }
99 
100  return true;
101 }
flags
Definition: http_parser.h:127
struct event event_
Definition: EventHandler.h:197
static void libeventCallback(libevent_fd_t fd, short events, void *arg)
auto event_ref_flags(struct event *ev) -> decltype(std::ref(ev->ev_flags))
Definition: EventUtil.h:41
fbstring errnoStr(int err)
Definition: String.cpp:463
bool isHandlerRegistered() const
Definition: EventHandler.h:112
bool folly::EventHandler::registerInternalHandler ( uint16_t  events)
inline

Register the handler as an internal event.

This event will not count as an active event for determining if the EventBase loop has more events to process. The EventBase loop runs only as long as there are active EventHandlers, however "internal" event handlers are not counted. Therefore this event handler will not prevent EventBase loop from exiting with no more work to do if there are no other non-internal event handlers registered.

This is intended to be used only in very rare cases by the internal EventBase code. This API is not guaranteed to remain stable or portable in the future.

Definition at line 183 of file EventHandler.h.

References ensureNotRegistered(), isPending(), libeventCallback(), registerImpl(), setEventBase(), and uint16_t.

183  {
184  return registerImpl(events, true);
185  }
bool registerImpl(uint16_t events, bool internal)
void folly::EventHandler::setEventBase ( EventBase eventBase)
private

Definition at line 168 of file EventHandler.cpp.

References event_, eventBase_, and folly::EventBase::getLibeventBase().

Referenced by attachEventBase(), EventHandler(), initHandler(), and registerInternalHandler().

168  {
169  event_base_set(eventBase->getLibeventBase(), &event_);
170  eventBase_ = eventBase;
171 }
struct event event_
Definition: EventHandler.h:197
EventBase * eventBase_
Definition: EventHandler.h:198

Member Data Documentation

EventBase* folly::EventHandler::eventBase_
private

Definition at line 198 of file EventHandler.h.

Referenced by EventHandler(), libeventCallback(), and setEventBase().


The documentation for this class was generated from the following files: