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