[Android WebView] Fix webview perf bot switchover to use org.chromium.webview_shell...
[chromium-blink-merge.git] / net / tools / epoll_server / epoll_server.h
blob92d6555ca6e154f6957275173526128af04d3932
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef NET_TOOLS_EPOLL_SERVER_EPOLL_SERVER_H_
6 #define NET_TOOLS_EPOLL_SERVER_EPOLL_SERVER_H_
8 #include <fcntl.h>
9 #include <sys/queue.h>
10 #include <map>
11 #include <set>
12 #include <string>
13 #include <utility>
14 #include <vector>
16 // #define EPOLL_SERVER_EVENT_TRACING 1
18 // Defining EPOLL_SERVER_EVENT_TRACING
19 // causes code to exist which didn't before.
20 // This code tracks each event generated by the epollserver,
21 // as well as providing a per-fd-registered summary of
22 // events. Note that enabling this code vastly slows
23 // down operations, and uses substantially more
24 // memory. For these reasons, it should only be enabled when doing
25 // developer debugging at his/her workstation.
27 // A structure called 'EventRecorder' will exist when
28 // the macro is defined. See the EventRecorder class interface
29 // within the EpollServer class for more details.
30 #ifdef EPOLL_SERVER_EVENT_TRACING
31 #include <ostream>
32 #include "base/logging.h"
33 #endif
35 #include "base/basictypes.h"
36 #include "base/compiler_specific.h"
37 #include "base/containers/hash_tables.h"
38 #include "base/memory/scoped_ptr.h"
39 #include <sys/epoll.h>
41 namespace net {
43 class EpollServer;
44 class EpollAlarmCallbackInterface;
45 class ReadPipeCallback;
47 struct EpollEvent {
48 EpollEvent(int events, bool is_epoll_wait)
49 : in_events(events),
50 out_ready_mask(0) {
53 int in_events; // incoming events
54 int out_ready_mask; // the new event mask for ready list (0 means don't
55 // get on the ready list). This field is always
56 // initialized to 0 when the event is passed to
57 // OnEvent.
60 // Callbacks which go into EpollServers are expected to derive from this class.
61 class EpollCallbackInterface {
62 public:
63 // Summary:
64 // Called when the callback is registered into a EpollServer.
65 // Args:
66 // eps - the poll server into which this callback was registered
67 // fd - the file descriptor which was registered
68 // event_mask - the event mask (composed of EPOLLIN, EPOLLOUT, etc)
69 // which was registered (and will initially be used
70 // in the epoll() calls)
71 virtual void OnRegistration(EpollServer* eps, int fd, int event_mask) = 0;
73 // Summary:
74 // Called when the event_mask is modified (for a file-descriptor)
75 // Args:
76 // fd - the file descriptor which was registered
77 // event_mask - the event mask (composed of EPOLLIN, EPOLLOUT, etc)
78 // which was is now curren (and will be used
79 // in subsequent epoll() calls)
80 virtual void OnModification(int fd, int event_mask) = 0;
82 // Summary:
83 // Called whenever an event occurs on the file-descriptor.
84 // This is where the bulk of processing is expected to occur.
85 // Args:
86 // fd - the file descriptor which was registered
87 // event - a struct that contains the event mask (composed of EPOLLIN,
88 // EPOLLOUT, etc), a flag that indicates whether this is a true
89 // epoll_wait event vs one from the ready list, and an output
90 // parameter for OnEvent to inform the EpollServer whether to put
91 // this fd on the ready list.
92 virtual void OnEvent(int fd, EpollEvent* event) = 0;
94 // Summary:
95 // Called when the file-descriptor is unregistered from the poll-server.
96 // Args:
97 // fd - the file descriptor which was registered, and of this call, is now
98 // unregistered.
99 // replaced - If true, this callback is being replaced by another, otherwise
100 // it is simply being removed.
101 virtual void OnUnregistration(int fd, bool replaced) = 0;
103 // Summary:
104 // Called when the epoll server is shutting down. This is different from
105 // OnUnregistration because the subclass may want to clean up memory.
106 // This is called in leiu of OnUnregistration.
107 // Args:
108 // fd - the file descriptor which was registered.
109 virtual void OnShutdown(EpollServer* eps, int fd) = 0;
111 virtual ~EpollCallbackInterface() {}
113 protected:
114 EpollCallbackInterface() {}
117 ////////////////////////////////////////////////////////////////////////////////
118 ////////////////////////////////////////////////////////////////////////////////
120 class EpollServer {
121 public:
122 typedef EpollAlarmCallbackInterface AlarmCB;
123 typedef EpollCallbackInterface CB;
125 typedef std::multimap<int64, AlarmCB*> TimeToAlarmCBMap;
126 typedef TimeToAlarmCBMap::iterator AlarmRegToken;
128 // Summary:
129 // Constructor:
130 // By default, we don't wait any amount of time for events, and
131 // we suggest to the epoll-system that we're going to use on-the-order
132 // of 1024 FDs.
133 EpollServer();
135 ////////////////////////////////////////
137 // Destructor
138 virtual ~EpollServer();
140 ////////////////////////////////////////
142 // Summary
143 // Register a callback to be called whenever an event contained
144 // in the set of events included in event_mask occurs on the
145 // file-descriptor 'fd'
147 // Note that only one callback is allowed to be registered for
148 // any specific file-decriptor.
150 // If a callback is registered for a file-descriptor which has already
151 // been registered, then the previous callback is unregistered with
152 // the 'replaced' flag set to true. I.e. the previous callback's
153 // OnUnregistration() function is called like so:
154 // OnUnregistration(fd, true);
156 // The epoll server does NOT take on ownership of the callback: the callback
157 // creator is responsible for managing that memory.
159 // Args:
160 // fd - a valid file-descriptor
161 // cb - an instance of a subclass of EpollCallbackInterface
162 // event_mask - a combination of (EPOLLOUT, EPOLLIN.. etc) indicating
163 // the events for which the callback would like to be
164 // called.
165 virtual void RegisterFD(int fd, CB* cb, int event_mask);
167 ////////////////////////////////////////
169 // Summary:
170 // A shortcut for RegisterFD which sets things up such that the
171 // callback is called when 'fd' is available for writing.
172 // Args:
173 // fd - a valid file-descriptor
174 // cb - an instance of a subclass of EpollCallbackInterface
175 virtual void RegisterFDForWrite(int fd, CB* cb);
177 ////////////////////////////////////////
179 // Summary:
180 // A shortcut for RegisterFD which sets things up such that the
181 // callback is called when 'fd' is available for reading or writing.
182 // Args:
183 // fd - a valid file-descriptor
184 // cb - an instance of a subclass of EpollCallbackInterface
185 virtual void RegisterFDForReadWrite(int fd, CB* cb);
187 ////////////////////////////////////////
189 // Summary:
190 // A shortcut for RegisterFD which sets things up such that the
191 // callback is called when 'fd' is available for reading.
192 // Args:
193 // fd - a valid file-descriptor
194 // cb - an instance of a subclass of EpollCallbackInterface
195 virtual void RegisterFDForRead(int fd, CB* cb);
197 ////////////////////////////////////////
199 // Summary:
200 // Removes the FD and the associated callback from the pollserver.
201 // If the callback is registered with other FDs, they will continue
202 // to be processed using the callback without modification.
203 // If the file-descriptor specified is not registered in the
204 // epoll_server, then nothing happens as a result of this call.
205 // Args:
206 // fd - the file-descriptor which should no-longer be monitored.
207 virtual void UnregisterFD(int fd);
209 ////////////////////////////////////////
211 // Summary:
212 // Modifies the event mask for the file-descriptor, replacing
213 // the old event_mask with the new one specified here.
214 // If the file-descriptor specified is not registered in the
215 // epoll_server, then nothing happens as a result of this call.
216 // Args:
217 // fd - the fd whose event mask should be modified.
218 // event_mask - the new event mask.
219 virtual void ModifyCallback(int fd, int event_mask);
221 ////////////////////////////////////////
223 // Summary:
224 // Modifies the event mask for the file-descriptor such that we
225 // no longer request events when 'fd' is readable.
226 // If the file-descriptor specified is not registered in the
227 // epoll_server, then nothing happens as a result of this call.
228 // Args:
229 // fd - the fd whose event mask should be modified.
230 virtual void StopRead(int fd);
232 ////////////////////////////////////////
234 // Summary:
235 // Modifies the event mask for the file-descriptor such that we
236 // request events when 'fd' is readable.
237 // If the file-descriptor specified is not registered in the
238 // epoll_server, then nothing happens as a result of this call.
239 // Args:
240 // fd - the fd whose event mask should be modified.
241 virtual void StartRead(int fd);
243 ////////////////////////////////////////
245 // Summary:
246 // Modifies the event mask for the file-descriptor such that we
247 // no longer request events when 'fd' is writable.
248 // If the file-descriptor specified is not registered in the
249 // epoll_server, then nothing happens as a result of this call.
250 // Args:
251 // fd - the fd whose event mask should be modified.
252 virtual void StopWrite(int fd);
254 ////////////////////////////////////////
256 // Summary:
257 // Modifies the event mask for the file-descriptor such that we
258 // request events when 'fd' is writable.
259 // If the file-descriptor specified is not registered in the
260 // epoll_server, then nothing happens as a result of this call.
261 // Args:
262 // fd - the fd whose event mask should be modified.
263 virtual void StartWrite(int fd);
265 ////////////////////////////////////////
267 // Summary:
268 // Looks up the callback associated with the file-desriptor 'fd'.
269 // If a callback is associated with this file-descriptor, then
270 // it's OnEvent() method is called with the file-descriptor 'fd',
271 // and event_mask 'event_mask'
273 // If no callback is registered for this file-descriptor, nothing
274 // will happen as a result of this call.
276 // This function is used internally by the EpollServer, but is
277 // available publically so that events might be 'faked'. Calling
278 // this function with an fd and event_mask is equivalent (as far
279 // as the callback is concerned) to having a real event generated
280 // by epoll (except, of course, that read(), etc won't necessarily
281 // be able to read anything)
282 // Args:
283 // fd - the file-descriptor on which an event has occured.
284 // event_mask - a bitmask representing the events which have occured
285 // on/for this fd. This bitmask is composed of
286 // POLLIN, POLLOUT, etc.
288 void HandleEvent(int fd, int event_mask);
290 // Summary:
291 // Call this when you want the pollserver to
292 // wait for events and execute the callbacks associated with
293 // the file-descriptors on which those events have occured.
294 // Depending on the value of timeout_in_us_, this may or may
295 // not return immediately. Please reference the set_timeout()
296 // function for the specific behaviour.
297 virtual void WaitForEventsAndExecuteCallbacks();
299 // Summary:
300 // When an fd is registered to use edge trigger notification, the ready
301 // list can be used to simulate level trigger semantics. Edge trigger
302 // registration doesn't send an initial event, and only rising edge (going
303 // from blocked to unblocked) events are sent. A callback can put itself on
304 // the ready list by calling SetFDReady() after calling RegisterFD(). The
305 // OnEvent method of all callbacks associated with the fds on the ready
306 // list will be called immediately after processing the events returned by
307 // epoll_wait(). The fd is removed from the ready list before the
308 // callback's OnEvent() method is invoked. To stay on the ready list, the
309 // OnEvent() (or some function in that call chain) must call SetFDReady
310 // again. When a fd is unregistered using UnregisterFD(), the fd is
311 // automatically removed from the ready list.
313 // When the callback for a edge triggered fd hits the falling edge (about
314 // to block, either because of it got an EAGAIN, or had a short read/write
315 // operation), it should remove itself from the ready list using
316 // SetFDNotReady() (since OnEvent cannot distinguish between invocation
317 // from the ready list vs from a normal epoll event). All four ready list
318 // methods are safe to be called within the context of the callbacks.
320 // Since the ready list invokes EpollCallbackInterface::OnEvent, only fds
321 // that are registered with the EpollServer will be put on the ready list.
322 // SetFDReady() and SetFDNotReady() will do nothing if the EpollServer
323 // doesn't know about the fd passed in.
325 // Since the ready list cannot reliably determine proper set of events
326 // which should be sent to the callback, SetFDReady() requests the caller
327 // to provide the ready list with the event mask, which will be used later
328 // when OnEvent() is invoked by the ready list. Hence, the event_mask
329 // passedto SetFDReady() does not affect the actual epoll registration of
330 // the fd with the kernel. If a fd is already put on the ready list, and
331 // SetFDReady() is called again for that fd with a different event_mask,
332 // the event_mask will be updated.
333 virtual void SetFDReady(int fd, int events_to_fake);
335 virtual void SetFDNotReady(int fd);
337 // Summary:
338 // IsFDReady(), ReadyListSize(), and VerifyReadyList are intended as
339 // debugging tools and for writing unit tests.
340 // ISFDReady() returns whether a fd is in the ready list.
341 // ReadyListSize() returns the number of fds on the ready list.
342 // VerifyReadyList() checks the consistency of internal data structure. It
343 // will CHECK if it finds an error.
344 virtual bool IsFDReady(int fd) const;
346 size_t ReadyListSize() const { return ready_list_size_; }
348 void VerifyReadyList() const;
350 ////////////////////////////////////////
352 // Summary:
353 // Registers an alarm 'ac' to go off at time 'timeout_time_in_us'.
354 // If the callback returns a positive number from its OnAlarm() function,
355 // then the callback will be re-registered at that time, else the alarm
356 // owner is responsible for freeing up memory.
358 // Important: A give AlarmCB* can not be registered again if it is already
359 // registered. If a user wants to register a callback again it should first
360 // unregister the previous callback before calling RegisterAlarm again.
361 // Args:
362 // timeout_time_in_us - the absolute time at which the alarm should go off
363 // ac - the alarm which will be called.
364 virtual void RegisterAlarm(int64 timeout_time_in_us, AlarmCB* ac);
366 // Summary:
367 // Registers an alarm 'ac' to go off at time: (ApproximateNowInUs() +
368 // delta_in_us). While this is somewhat less accurate (see the description
369 // for ApproximateNowInUs() to see how 'approximate'), the error is never
370 // worse than the amount of time it takes to process all events in one
371 // WaitForEvents. As with 'RegisterAlarm()', if the callback returns a
372 // positive number from its OnAlarm() function, then the callback will be
373 // re-registered at that time, else the alarm owner is responsible for
374 // freeing up memory.
375 // Note that this function is purely a convienence. The
376 // same thing may be accomplished by using RegisterAlarm with
377 // ApproximateNowInUs() directly.
379 // Important: A give AlarmCB* can not be registered again if it is already
380 // registered. If a user wants to register a callback again it should first
381 // unregister the previous callback before calling RegisterAlarm again.
382 // Args:
383 // delta_in_us - the delta in microseconds from the ApproximateTimeInUs() at
384 // which point the alarm should go off.
385 // ac - the alarm which will be called.
386 void RegisterAlarmApproximateDelta(int64 delta_in_us, AlarmCB* ac) {
387 RegisterAlarm(ApproximateNowInUsec() + delta_in_us, ac);
390 ////////////////////////////////////////
392 // Summary:
393 // Unregister the alarm referred to by iterator_token; Callers should
394 // be warned that a token may have become already invalid when OnAlarm()
395 // is called, was unregistered, or OnShutdown was called on that alarm.
396 // Args:
397 // iterator_token - iterator to the alarm callback to unregister.
398 virtual void UnregisterAlarm(
399 const EpollServer::AlarmRegToken& iterator_token);
401 ////////////////////////////////////////
403 // Summary:
404 // returns the number of file-descriptors registered in this EpollServer.
405 // Returns:
406 // number of FDs registered (discounting the internal pipe used for Wake)
407 virtual int NumFDsRegistered() const;
409 // Summary:
410 // Force the epoll server to wake up (by writing to an internal pipe).
411 virtual void Wake();
413 // Summary:
414 // Wrapper around WallTimer's NowInUsec. We do this so that we can test
415 // EpollServer without using the system clock (and can avoid the flakiness
416 // that would ensue)
417 // Returns:
418 // the current time as number of microseconds since the Unix epoch.
419 virtual int64 NowInUsec() const;
421 // Summary:
422 // Since calling NowInUsec() many thousands of times per
423 // WaitForEventsAndExecuteCallbacks function call is, to say the least,
424 // inefficient, we allow users to use an approximate time instead. The
425 // time returned from this function is as accurate as NowInUsec() when
426 // WaitForEventsAndExecuteCallbacks is not an ancestor of the caller's
427 // callstack.
428 // However, when WaitForEventsAndExecuteCallbacks -is- an ancestor, then
429 // this function returns the time at which the
430 // WaitForEventsAndExecuteCallbacks function started to process events or
431 // alarms.
433 // Essentially, this function makes available a fast and mostly accurate
434 // mechanism for getting the time for any function handling an event or
435 // alarm. When functions which are not handling callbacks or alarms call
436 // this function, they get the slow and "absolutely" accurate time.
438 // Users should be encouraged to use this function.
439 // Returns:
440 // the "approximate" current time as number of microseconds since the Unix
441 // epoch.
442 virtual int64 ApproximateNowInUsec() const;
444 static std::string EventMaskToString(int event_mask);
446 // Summary:
447 // Logs the state of the epoll server with LOG(ERROR).
448 void LogStateOnCrash();
450 // Summary:
451 // Set the timeout to the value specified.
452 // If the timeout is set to a negative number,
453 // WaitForEventsAndExecuteCallbacks() will only return when an event has
454 // occured
455 // If the timeout is set to zero,
456 // WaitForEventsAndExecuteCallbacks() will return immediately
457 // If the timeout is set to a positive number,
458 // WaitForEventsAndExecuteCallbacks() will return when an event has
459 // occured, or when timeout_in_us microseconds has elapsed, whichever
460 // is first.
461 // Args:
462 // timeout_in_us - value specified depending on behaviour desired.
463 // See above.
464 void set_timeout_in_us(int64 timeout_in_us) {
465 timeout_in_us_ = timeout_in_us;
468 ////////////////////////////////////////
470 // Summary:
471 // Accessor for the current value of timeout_in_us.
472 int timeout_in_us() const { return timeout_in_us_; }
474 // Summary:
475 // Returns true when the EpollServer() is being destroyed.
476 bool in_shutdown() const { return in_shutdown_; }
478 bool ContainsAlarm(EpollAlarmCallbackInterface* alarm) const {
479 return all_alarms_.find(alarm) != all_alarms_.end();
482 // Summary:
483 // A function for implementing the ready list. It invokes OnEvent for each
484 // of the fd in the ready list, and takes care of adding them back to the
485 // ready list if the callback requests it (by checking that out_ready_mask
486 // is non-zero).
487 void CallReadyListCallbacks();
489 protected:
490 virtual int GetFlags(int fd);
491 inline int SetFlags(int fd, int flags) {
492 return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
495 virtual void SetNonblocking(int fd);
497 // This exists here so that we can override this function in unittests
498 // in order to make effective mock EpollServer objects.
499 virtual int epoll_wait_impl(int epfd,
500 struct epoll_event* events,
501 int max_events,
502 int timeout_in_ms);
504 // this struct is used internally, and is never used by anything external
505 // to this class. Some of its members are declared mutable to get around the
506 // restriction imposed by hash_set. Since hash_set knows nothing about the
507 // objects it stores, it has to assume that every bit of the object is used
508 // in the hash function and equal_to comparison. Thus hash_set::iterator is a
509 // const iterator. In this case, the only thing that must stay constant is
510 // fd. Everything else are just along for the ride and changing them doesn't
511 // compromise the hash_set integrity.
512 struct CBAndEventMask {
513 CBAndEventMask()
514 : cb(NULL),
515 fd(-1),
516 event_mask(0),
517 events_asserted(0),
518 events_to_fake(0),
519 in_use(false) {
520 entry.le_next = NULL;
521 entry.le_prev = NULL;
524 CBAndEventMask(EpollCallbackInterface* cb,
525 int event_mask,
526 int fd)
527 : cb(cb), fd(fd), event_mask(event_mask), events_asserted(0),
528 events_to_fake(0), in_use(false) {
529 entry.le_next = NULL;
530 entry.le_prev = NULL;
533 // Required operator for hash_set. Normally operator== should be a free
534 // standing function. However, since CBAndEventMask is a protected type and
535 // it will never be a base class, it makes no difference.
536 bool operator==(const CBAndEventMask& cb_and_mask) const {
537 return fd == cb_and_mask.fd;
539 // A callback. If the fd is unregistered inside the callchain of OnEvent,
540 // the cb will be set to NULL.
541 mutable EpollCallbackInterface* cb;
543 mutable LIST_ENTRY(CBAndEventMask) entry;
544 // file descriptor registered with the epoll server.
545 int fd;
546 // the current event_mask registered for this callback.
547 mutable int event_mask;
548 // the event_mask that was returned by epoll
549 mutable int events_asserted;
550 // the event_mask for the ready list to use to call OnEvent.
551 mutable int events_to_fake;
552 // toggle around calls to OnEvent to tell UnregisterFD to not erase the
553 // iterator because HandleEvent is using it.
554 mutable bool in_use;
557 // Custom hash function to be used by hash_set.
558 struct CBAndEventMaskHash {
559 size_t operator()(const CBAndEventMask& cb_and_eventmask) const {
560 return static_cast<size_t>(cb_and_eventmask.fd);
564 typedef base::hash_set<CBAndEventMask, CBAndEventMaskHash> FDToCBMap;
566 // the following four functions are OS-specific, and are likely
567 // to be changed in a subclass if the poll/select method is changed
568 // from epoll.
570 // Summary:
571 // Deletes a file-descriptor from the set of FDs that should be
572 // monitored with epoll.
573 // Note that this only deals with modifying data relating -directly-
574 // with the epoll call-- it does not modify any data within the
575 // epoll_server.
576 // Args:
577 // fd - the file descriptor to-be-removed from the monitoring set
578 virtual void DelFD(int fd) const;
580 ////////////////////////////////////////
582 // Summary:
583 // Adds a file-descriptor to the set of FDs that should be
584 // monitored with epoll.
585 // Note that this only deals with modifying data relating -directly-
586 // with the epoll call.
587 // Args:
588 // fd - the file descriptor to-be-added to the monitoring set
589 // event_mask - the event mask (consisting of EPOLLIN, EPOLLOUT, etc
590 // OR'd together) which will be associated with this
591 // FD initially.
592 virtual void AddFD(int fd, int event_mask) const;
594 ////////////////////////////////////////
596 // Summary:
597 // Modifies a file-descriptor in the set of FDs that should be
598 // monitored with epoll.
599 // Note that this only deals with modifying data relating -directly-
600 // with the epoll call.
601 // Args:
602 // fd - the file descriptor to-be-added to the monitoring set
603 // event_mask - the event mask (consisting of EPOLLIN, EPOLLOUT, etc
604 // OR'd together) which will be associated with this
605 // FD after this call.
606 virtual void ModFD(int fd, int event_mask) const;
608 ////////////////////////////////////////
610 // Summary:
611 // Modified the event mask associated with an FD in the set of
612 // data needed by epoll.
613 // Events are removed before they are added, thus, if ~0 is put
614 // in 'remove_event', whatever is put in 'add_event' will be
615 // the new event mask.
616 // If the file-descriptor specified is not registered in the
617 // epoll_server, then nothing happens as a result of this call.
618 // Args:
619 // fd - the file descriptor whose event mask is to be modified
620 // remove_event - the events which are to be removed from the current
621 // event_mask
622 // add_event - the events which are to be added to the current event_mask
625 virtual void ModifyFD(int fd, int remove_event, int add_event);
627 ////////////////////////////////////////
629 // Summary:
630 // Waits for events, and calls HandleEvents() for each
631 // fd, event pair discovered to possibly have an event.
632 // Note that a callback (B) may get a spurious event if
633 // another callback (A) has closed a file-descriptor N, and
634 // the callback (B) has a newly opened file-descriptor, which
635 // also happens to be N.
636 virtual void WaitForEventsAndCallHandleEvents(int64 timeout_in_us,
637 struct epoll_event events[],
638 int events_size);
642 // Summary:
643 // An internal function for implementing the ready list. It adds a fd's
644 // CBAndEventMask to the ready list. If the fd is already on the ready
645 // list, it is a no-op.
646 void AddToReadyList(CBAndEventMask* cb_and_mask);
648 // Summary:
649 // An internal function for implementing the ready list. It remove a fd's
650 // CBAndEventMask from the ready list. If the fd is not on the ready list,
651 // it is a no-op.
652 void RemoveFromReadyList(const CBAndEventMask& cb_and_mask);
654 // Summary:
655 // Calls any pending alarms that should go off and reregisters them if they
656 // were recurring.
657 virtual void CallAndReregisterAlarmEvents();
659 // The file-descriptor created for epolling
660 int epoll_fd_;
662 // The mapping of file-descriptor to CBAndEventMasks
663 FDToCBMap cb_map_;
665 // Custom hash function to be used by hash_set.
666 struct AlarmCBHash {
667 size_t operator()(AlarmCB*const& p) const {
668 return reinterpret_cast<size_t>(p);
673 // TOOD(sushantj): Having this hash_set is avoidable. We currently have it
674 // only so that we can enforce stringent checks that a caller can not register
675 // the same alarm twice. One option is to have an implementation in which
676 // this hash_set is used only in the debug mode.
677 typedef base::hash_set<AlarmCB*, AlarmCBHash> AlarmCBMap;
678 AlarmCBMap all_alarms_;
680 TimeToAlarmCBMap alarm_map_;
682 // The amount of time in microseconds that we'll wait before returning
683 // from the WaitForEventsAndExecuteCallbacks() function.
684 // If this is positive, wait that many microseconds.
685 // If this is negative, wait forever, or for the first event that occurs
686 // If this is zero, never wait for an event.
687 int64 timeout_in_us_;
689 // This is nonzero only after the invocation of epoll_wait_impl within
690 // WaitForEventsAndCallHandleEvents and before the function
691 // WaitForEventsAndExecuteCallbacks returns. At all other times, this is
692 // zero. This enables us to have relatively accurate time returned from the
693 // ApproximateNowInUs() function. See that function for more details.
694 int64 recorded_now_in_us_;
696 // This is used to implement CallAndReregisterAlarmEvents. This stores
697 // all alarms that were reregistered because OnAlarm() returned a
698 // value > 0 and the time at which they should be executed is less that
699 // the current time. By storing such alarms in this map we ensure
700 // that while calling CallAndReregisterAlarmEvents we do not call
701 // OnAlarm on any alarm in this set. This ensures that we do not
702 // go in an infinite loop.
703 AlarmCBMap alarms_reregistered_and_should_be_skipped_;
705 LIST_HEAD(ReadyList, CBAndEventMask) ready_list_;
706 LIST_HEAD(TmpList, CBAndEventMask) tmp_list_;
707 int ready_list_size_;
708 // TODO(alyssar): make this into something that scales up.
709 static const int events_size_ = 256;
710 struct epoll_event events_[256];
712 #ifdef EPOLL_SERVER_EVENT_TRACING
713 struct EventRecorder {
714 public:
715 EventRecorder() : num_records_(0), record_threshold_(10000) {}
717 ~EventRecorder() {
718 Clear();
721 // When a number of events equals the record threshold,
722 // the collected data summary for all FDs will be written
723 // to LOG(INFO). Note that this does not include the
724 // individual events (if you'reinterested in those, you'll
725 // have to get at them programmatically).
726 // After any such flushing to LOG(INFO) all events will
727 // be cleared.
728 // Note that the definition of an 'event' is a bit 'hazy',
729 // as it includes the 'Unregistration' event, and perhaps
730 // others.
731 void set_record_threshold(int64 new_threshold) {
732 record_threshold_ = new_threshold;
735 void Clear() {
736 for (int i = 0; i < debug_events_.size(); ++i) {
737 delete debug_events_[i];
739 debug_events_.clear();
740 unregistered_fds_.clear();
741 event_counts_.clear();
744 void MaybeRecordAndClear() {
745 ++num_records_;
746 if ((num_records_ > record_threshold_) &&
747 (record_threshold_ > 0)) {
748 LOG(INFO) << "\n" << *this;
749 num_records_ = 0;
750 Clear();
754 void RecordFDMaskEvent(int fd, int mask, const char* function) {
755 FDMaskOutput* fdmo = new FDMaskOutput(fd, mask, function);
756 debug_events_.push_back(fdmo);
757 MaybeRecordAndClear();
760 void RecordEpollWaitEvent(int timeout_in_ms,
761 int num_events_generated) {
762 EpollWaitOutput* ewo = new EpollWaitOutput(timeout_in_ms,
763 num_events_generated);
764 debug_events_.push_back(ewo);
765 MaybeRecordAndClear();
768 void RecordEpollEvent(int fd, int event_mask) {
769 Events& events_for_fd = event_counts_[fd];
770 events_for_fd.AssignFromMask(event_mask);
771 MaybeRecordAndClear();
774 friend ostream& operator<<(ostream& os, const EventRecorder& er) {
775 for (int i = 0; i < er.unregistered_fds_.size(); ++i) {
776 os << "fd: " << er.unregistered_fds_[i] << "\n";
777 os << er.unregistered_fds_[i];
779 for (EventCountsMap::const_iterator i = er.event_counts_.begin();
780 i != er.event_counts_.end();
781 ++i) {
782 os << "fd: " << i->first << "\n";
783 os << i->second;
785 for (int i = 0; i < er.debug_events_.size(); ++i) {
786 os << *(er.debug_events_[i]) << "\n";
788 return os;
791 void RecordUnregistration(int fd) {
792 EventCountsMap::iterator i = event_counts_.find(fd);
793 if (i != event_counts_.end()) {
794 unregistered_fds_.push_back(i->second);
795 event_counts_.erase(i);
797 MaybeRecordAndClear();
800 protected:
801 class DebugOutput {
802 public:
803 friend ostream& operator<<(ostream& os, const DebugOutput& debug_output) {
804 debug_output.OutputToStream(os);
805 return os;
807 virtual void OutputToStream(ostream* os) const = 0;
808 virtual ~DebugOutput() {}
811 class FDMaskOutput : public DebugOutput {
812 public:
813 FDMaskOutput(int fd, int mask, const char* function) :
814 fd_(fd), mask_(mask), function_(function) {}
815 virtual void OutputToStream(ostream* os) const {
816 (*os) << "func: " << function_
817 << "\tfd: " << fd_;
818 if (mask_ != 0) {
819 (*os) << "\tmask: " << EventMaskToString(mask_);
822 int fd_;
823 int mask_;
824 const char* function_;
827 class EpollWaitOutput : public DebugOutput {
828 public:
829 EpollWaitOutput(int timeout_in_ms,
830 int num_events_generated) :
831 timeout_in_ms_(timeout_in_ms),
832 num_events_generated_(num_events_generated) {}
833 virtual void OutputToStream(ostream* os) const {
834 (*os) << "timeout_in_ms: " << timeout_in_ms_
835 << "\tnum_events_generated: " << num_events_generated_;
837 protected:
838 int timeout_in_ms_;
839 int num_events_generated_;
842 struct Events {
843 Events() :
844 epoll_in(0),
845 epoll_pri(0),
846 epoll_out(0),
847 epoll_rdnorm(0),
848 epoll_rdband(0),
849 epoll_wrnorm(0),
850 epoll_wrband(0),
851 epoll_msg(0),
852 epoll_err(0),
853 epoll_hup(0),
854 epoll_oneshot(0),
855 epoll_et(0) {}
857 void AssignFromMask(int event_mask) {
858 if (event_mask & EPOLLIN) ++epoll_in;
859 if (event_mask & EPOLLPRI) ++epoll_pri;
860 if (event_mask & EPOLLOUT) ++epoll_out;
861 if (event_mask & EPOLLRDNORM) ++epoll_rdnorm;
862 if (event_mask & EPOLLRDBAND) ++epoll_rdband;
863 if (event_mask & EPOLLWRNORM) ++epoll_wrnorm;
864 if (event_mask & EPOLLWRBAND) ++epoll_wrband;
865 if (event_mask & EPOLLMSG) ++epoll_msg;
866 if (event_mask & EPOLLERR) ++epoll_err;
867 if (event_mask & EPOLLHUP) ++epoll_hup;
868 if (event_mask & EPOLLONESHOT) ++epoll_oneshot;
869 if (event_mask & EPOLLET) ++epoll_et;
872 friend ostream& operator<<(ostream& os, const Events& ev) {
873 if (ev.epoll_in) {
874 os << "\t EPOLLIN: " << ev.epoll_in << "\n";
876 if (ev.epoll_pri) {
877 os << "\t EPOLLPRI: " << ev.epoll_pri << "\n";
879 if (ev.epoll_out) {
880 os << "\t EPOLLOUT: " << ev.epoll_out << "\n";
882 if (ev.epoll_rdnorm) {
883 os << "\t EPOLLRDNORM: " << ev.epoll_rdnorm << "\n";
885 if (ev.epoll_rdband) {
886 os << "\t EPOLLRDBAND: " << ev.epoll_rdband << "\n";
888 if (ev.epoll_wrnorm) {
889 os << "\t EPOLLWRNORM: " << ev.epoll_wrnorm << "\n";
891 if (ev.epoll_wrband) {
892 os << "\t EPOLLWRBAND: " << ev.epoll_wrband << "\n";
894 if (ev.epoll_msg) {
895 os << "\t EPOLLMSG: " << ev.epoll_msg << "\n";
897 if (ev.epoll_err) {
898 os << "\t EPOLLERR: " << ev.epoll_err << "\n";
900 if (ev.epoll_hup) {
901 os << "\t EPOLLHUP: " << ev.epoll_hup << "\n";
903 if (ev.epoll_oneshot) {
904 os << "\t EPOLLONESHOT: " << ev.epoll_oneshot << "\n";
906 if (ev.epoll_et) {
907 os << "\t EPOLLET: " << ev.epoll_et << "\n";
909 return os;
912 unsigned int epoll_in;
913 unsigned int epoll_pri;
914 unsigned int epoll_out;
915 unsigned int epoll_rdnorm;
916 unsigned int epoll_rdband;
917 unsigned int epoll_wrnorm;
918 unsigned int epoll_wrband;
919 unsigned int epoll_msg;
920 unsigned int epoll_err;
921 unsigned int epoll_hup;
922 unsigned int epoll_oneshot;
923 unsigned int epoll_et;
926 std::vector<DebugOutput*> debug_events_;
927 std::vector<Events> unregistered_fds_;
928 typedef base::hash_map<int, Events> EventCountsMap;
929 EventCountsMap event_counts_;
930 int64 num_records_;
931 int64 record_threshold_;
934 void ClearEventRecords() {
935 event_recorder_.Clear();
937 void WriteEventRecords(ostream* os) const {
938 (*os) << event_recorder_;
941 mutable EventRecorder event_recorder_;
943 #endif
945 private:
946 // Helper functions used in the destructor.
947 void CleanupFDToCBMap();
948 void CleanupTimeToAlarmCBMap();
950 // The callback registered to the fds below. As the purpose of their
951 // registration is to wake the epoll server it just clears the pipe and
952 // returns.
953 scoped_ptr<ReadPipeCallback> wake_cb_;
955 // A pipe owned by the epoll server. The server will be registered to listen
956 // on read_fd_ and can be woken by Wake() which writes to write_fd_.
957 int read_fd_;
958 int write_fd_;
960 // This boolean is checked to see if it is false at the top of the
961 // WaitForEventsAndExecuteCallbacks function. If not, then it either returns
962 // without doing work, and logs to ERROR, or aborts the program (in
963 // DEBUG mode). If so, then it sets the bool to true, does work, and
964 // sets it back to false when done. This catches unwanted recursion.
965 bool in_wait_for_events_and_execute_callbacks_;
967 // Returns true when the EpollServer() is being destroyed.
968 bool in_shutdown_;
970 DISALLOW_COPY_AND_ASSIGN(EpollServer);
973 class EpollAlarmCallbackInterface {
974 public:
975 // Summary:
976 // Called when an alarm times out. Invalidates an AlarmRegToken.
977 // WARNING: If a token was saved to refer to an alarm callback, OnAlarm must
978 // delete it, as the reference is no longer valid.
979 // Returns:
980 // the unix time (in microseconds) at which this alarm should be signaled
981 // again, or 0 if the alarm should be removed.
982 virtual int64 OnAlarm() = 0;
984 // Summary:
985 // Called when the an alarm is registered. Invalidates an AlarmRegToken.
986 // Args:
987 // token: the iterator to the the alarm registered in the alarm map.
988 // WARNING: this token becomes invalid when the alarm fires, is
989 // unregistered, or OnShutdown is called on that alarm.
990 // eps: the epoll server the alarm is registered with.
991 virtual void OnRegistration(const EpollServer::AlarmRegToken& token,
992 EpollServer* eps) = 0;
994 // Summary:
995 // Called when the an alarm is unregistered.
996 // WARNING: It is not valid to unregister a callback and then use the token
997 // that was saved to refer to the callback.
998 virtual void OnUnregistration() = 0;
1000 // Summary:
1001 // Called when the epoll server is shutting down.
1002 // Invalidates the AlarmRegToken that was given when this alarm was
1003 // registered.
1004 virtual void OnShutdown(EpollServer* eps) = 0;
1006 virtual ~EpollAlarmCallbackInterface() {}
1008 protected:
1009 EpollAlarmCallbackInterface() {}
1012 // A simple alarm which unregisters itself on destruction.
1014 // PLEASE NOTE:
1015 // Any classes overriding these functions must either call the implementation
1016 // of the parent class, or is must otherwise make sure that the 'registered_'
1017 // boolean and the token, 'token_', are updated appropriately.
1018 class EpollAlarm : public EpollAlarmCallbackInterface {
1019 public:
1020 EpollAlarm();
1022 ~EpollAlarm() override;
1024 // Marks the alarm as unregistered and returns 0. The return value may be
1025 // safely ignored by subclasses.
1026 int64 OnAlarm() override;
1028 // Marks the alarm as registered, and stores the token.
1029 void OnRegistration(const EpollServer::AlarmRegToken& token,
1030 EpollServer* eps) override;
1032 // Marks the alarm as unregistered.
1033 void OnUnregistration() override;
1035 // Marks the alarm as unregistered.
1036 void OnShutdown(EpollServer* eps) override;
1038 // If the alarm was registered, unregister it.
1039 void UnregisterIfRegistered();
1041 bool registered() const { return registered_; }
1043 const EpollServer* eps() const { return eps_; }
1045 private:
1046 EpollServer::AlarmRegToken token_;
1047 EpollServer* eps_;
1048 bool registered_;
1051 } // namespace net
1053 #endif // NET_TOOLS_EPOLL_SERVER_EPOLL_SERVER_H_