Consistency in namespace-closing comments
[folly.git] / folly / io / async / EventHandler.cpp
1 /*
2  * Copyright 2004-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
17 #include <folly/io/async/EventHandler.h>
18 #include <folly/io/async/EventBase.h>
19
20 #include <assert.h>
21
22 namespace folly {
23
24 EventHandler::EventHandler(EventBase* eventBase, int fd) {
25   folly_event_set(&event_, fd, 0, &EventHandler::libeventCallback, this);
26   if (eventBase != nullptr) {
27     setEventBase(eventBase);
28   } else {
29     // Callers must set the EventBase and fd before using this timeout.
30     // Set event_->ev_base to nullptr to ensure that this happens.
31     // (otherwise libevent will initialize it to the "default" event_base)
32     event_.ev_base = nullptr;
33     eventBase_ = nullptr;
34   }
35 }
36
37 EventHandler::~EventHandler() {
38   unregisterHandler();
39 }
40
41 bool EventHandler::registerImpl(uint16_t events, bool internal) {
42   assert(event_.ev_base != nullptr);
43
44   // We have to unregister the event before we can change the event flags
45   if (isHandlerRegistered()) {
46     // If the new events are the same are the same as the already registered
47     // flags, we don't have to do anything.  Just return.
48     auto flags = event_ref_flags(&event_);
49     if (events == event_.ev_events &&
50         static_cast<bool>(flags & EVLIST_INTERNAL) == internal) {
51       return true;
52     }
53
54     event_del(&event_);
55   }
56
57   // Update the event flags
58   // Unfortunately, event_set() resets the event_base, so we have to remember
59   // it before hand, then pass it back into event_base_set() afterwards
60   struct event_base* evb = event_.ev_base;
61   event_set(
62       &event_,
63       event_.ev_fd,
64       short(events),
65       &EventHandler::libeventCallback,
66       this);
67   event_base_set(evb, &event_);
68
69   // Set EVLIST_INTERNAL if this is an internal event
70   if (internal) {
71     event_ref_flags(&event_) |= EVLIST_INTERNAL;
72   }
73
74   // Add the event.
75   //
76   // Although libevent allows events to wait on both I/O and a timeout,
77   // we intentionally don't allow an EventHandler to also use a timeout.
78   // Callers must maintain a separate AsyncTimeout object if they want a
79   // timeout.
80   //
81   // Otherwise, it is difficult to handle persistent events properly.  (The I/O
82   // event and timeout may both fire together the same time around the event
83   // loop.  Normally we would want to inform the caller of the I/O event first,
84   // then the timeout.  However, it is difficult to do this properly since the
85   // I/O callback could delete the EventHandler.)  Additionally, if a caller
86   // uses the same struct event for both I/O and timeout, and they just want to
87   // reschedule the timeout, libevent currently makes an epoll_ctl() call even
88   // if the I/O event flags haven't changed.  Using a separate event struct is
89   // therefore slightly more efficient in this case (although it does take up
90   // more space).
91   if (event_add(&event_, nullptr) < 0) {
92     LOG(ERROR) << "EventBase: failed to register event handler for fd "
93                << event_.ev_fd << ": " << strerror(errno);
94     // Call event_del() to make sure the event is completely uninstalled
95     event_del(&event_);
96     return false;
97   }
98
99   return true;
100 }
101
102 void EventHandler::unregisterHandler() {
103   if (isHandlerRegistered()) {
104     event_del(&event_);
105   }
106 }
107
108 void EventHandler::attachEventBase(EventBase* eventBase) {
109   // attachEventBase() may only be called on detached handlers
110   assert(event_.ev_base == nullptr);
111   assert(!isHandlerRegistered());
112   // This must be invoked from the EventBase's thread
113   eventBase->dcheckIsInEventBaseThread();
114
115   setEventBase(eventBase);
116 }
117
118 void EventHandler::detachEventBase() {
119   ensureNotRegistered(__func__);
120   event_.ev_base = nullptr;
121 }
122
123 void EventHandler::changeHandlerFD(int fd) {
124   ensureNotRegistered(__func__);
125   // event_set() resets event_base.ev_base, so manually restore it afterwards
126   struct event_base* evb = event_.ev_base;
127   folly_event_set(&event_, fd, 0, &EventHandler::libeventCallback, this);
128   event_.ev_base = evb; // don't use event_base_set(), since evb may be nullptr
129 }
130
131 void EventHandler::initHandler(EventBase* eventBase, int fd) {
132   ensureNotRegistered(__func__);
133   folly_event_set(&event_, fd, 0, &EventHandler::libeventCallback, this);
134   setEventBase(eventBase);
135 }
136
137 void EventHandler::ensureNotRegistered(const char* fn) {
138   // Neither the EventBase nor file descriptor may be changed while the
139   // handler is registered.  Treat it as a programmer bug and abort the program
140   // if this requirement is violated.
141   if (isHandlerRegistered()) {
142     LOG(ERROR) << fn << " called on registered handler; aborting";
143     abort();
144   }
145 }
146
147 void EventHandler::libeventCallback(libevent_fd_t fd, short events, void* arg) {
148   EventHandler* handler = reinterpret_cast<EventHandler*>(arg);
149   assert(fd == handler->event_.ev_fd);
150   (void)fd; // prevent unused variable warnings
151
152   auto observer = handler->eventBase_->getExecutionObserver();
153   if (observer) {
154     observer->starting(reinterpret_cast<uintptr_t>(handler));
155   }
156
157   // this can't possibly fire if handler->eventBase_ is nullptr
158   handler->eventBase_->bumpHandlingTime();
159
160   handler->handlerReady(uint16_t(events));
161
162   if (observer) {
163     observer->stopped(reinterpret_cast<uintptr_t>(handler));
164   }
165 }
166
167 void EventHandler::setEventBase(EventBase* eventBase) {
168   event_base_set(eventBase->getLibeventBase(), &event_);
169   eventBase_ = eventBase;
170 }
171
172 bool EventHandler::isPending() const {
173   if (event_ref_flags(&event_) & EVLIST_ACTIVE) {
174     if (event_.ev_res & EV_READ) {
175       return true;
176     }
177   }
178   return false;
179 }
180
181 } // namespace folly