14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifndef NET_TOOLS_EPOLL_SERVER_EPOLL_SERVER_H_
64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#define NET_TOOLS_EPOLL_SERVER_EPOLL_SERVER_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/queue.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <set>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// #define EPOLL_SERVER_EVENT_TRACING 1
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Defining EPOLL_SERVER_EVENT_TRACING
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// causes code to exist which didn't before.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This code tracks each event generated by the epollserver,
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as well as providing a per-fd-registered summary of
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// events. Note that enabling this code vastly slows
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// down operations, and uses substantially more
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// memory. For these reasons, it should only be enabled when doing
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// developer debugging at his/her workstation.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A structure called 'EventRecorder' will exist when
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the macro is defined. See the EventRecorder class interface
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// within the EpollServer class for more details.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef EPOLL_SERVER_EVENT_TRACING
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ostream>
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/containers/hash_tables.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/epoll.h>
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class EpollServer;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class EpollAlarmCallbackInterface;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ReadPipeCallback;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct EpollEvent {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EpollEvent(int events, bool is_epoll_wait)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : in_events(events),
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        out_ready_mask(0) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int in_events;            // incoming events
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int out_ready_mask;       // the new event mask for ready list (0 means don't
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            // get on the ready list). This field is always
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            // initialized to 0 when the event is passed to
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            // OnEvent.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Callbacks which go into EpollServers are expected to derive from this class.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class EpollCallbackInterface {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Called when the callback is registered into a EpollServer.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   eps - the poll server into which this callback was registered
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - the file descriptor which was registered
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   event_mask - the event mask (composed of EPOLLIN, EPOLLOUT, etc)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                which was registered (and will initially be used
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                in the epoll() calls)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnRegistration(EpollServer* eps, int fd, int event_mask) = 0;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Called when the event_mask is modified (for a file-descriptor)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - the file descriptor which was registered
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   event_mask - the event mask (composed of EPOLLIN, EPOLLOUT, etc)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                which was is now curren (and will be used
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                in subsequent epoll() calls)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnModification(int fd, int event_mask) = 0;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Called whenever an event occurs on the file-descriptor.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   This is where the bulk of processing is expected to occur.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - the file descriptor which was registered
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   event - a struct that contains the event mask (composed of EPOLLIN,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //           EPOLLOUT, etc), a flag that indicates whether this is a true
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //           epoll_wait event vs one from the ready list, and an output
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //           parameter for OnEvent to inform the EpollServer whether to put
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //           this fd on the ready list.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnEvent(int fd, EpollEvent* event) = 0;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Called when the file-descriptor is unregistered from the poll-server.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - the file descriptor which was registered, and of this call, is now
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //        unregistered.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   replaced - If true, this callback is being replaced by another, otherwise
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //              it is simply being removed.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnUnregistration(int fd, bool replaced) = 0;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Called when the epoll server is shutting down.  This is different from
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   OnUnregistration because the subclass may want to clean up memory.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   This is called in leiu of OnUnregistration.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  fd - the file descriptor which was registered.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnShutdown(EpollServer* eps, int fd) = 0;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~EpollCallbackInterface() {}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EpollCallbackInterface() {}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class EpollServer {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef EpollAlarmCallbackInterface AlarmCB;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef EpollCallbackInterface CB;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::multimap<int64, AlarmCB*> TimeToAlarmCBMap;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef TimeToAlarmCBMap::iterator AlarmRegToken;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Constructor:
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    By default, we don't wait any amount of time for events, and
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    we suggest to the epoll-system that we're going to use on-the-order
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    of 1024 FDs.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EpollServer();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Destructor
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~EpollServer();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Register a callback to be called whenever an event contained
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   in the set of events included in event_mask occurs on the
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   file-descriptor 'fd'
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Note that only one callback is allowed to be registered for
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   any specific file-decriptor.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   If a callback is registered for a file-descriptor which has already
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   been registered, then the previous callback is unregistered with
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   the 'replaced' flag set to true. I.e. the previous callback's
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   OnUnregistration() function is called like so:
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      OnUnregistration(fd, true);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  The epoll server does NOT take on ownership of the callback: the callback
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  creator is responsible for managing that memory.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - a valid file-descriptor
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   cb - an instance of a subclass of EpollCallbackInterface
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   event_mask - a combination of (EPOLLOUT, EPOLLIN.. etc) indicating
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                the events for which the callback would like to be
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                called.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RegisterFD(int fd, CB* cb, int event_mask);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   A shortcut for RegisterFD which sets things up such that the
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   callback is called when 'fd' is available for writing.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - a valid file-descriptor
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   cb - an instance of a subclass of EpollCallbackInterface
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RegisterFDForWrite(int fd, CB* cb);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   A shortcut for RegisterFD which sets things up such that the
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   callback is called when 'fd' is available for reading or writing.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - a valid file-descriptor
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   cb - an instance of a subclass of EpollCallbackInterface
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RegisterFDForReadWrite(int fd, CB* cb);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   A shortcut for RegisterFD which sets things up such that the
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   callback is called when 'fd' is available for reading.
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - a valid file-descriptor
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   cb - an instance of a subclass of EpollCallbackInterface
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RegisterFDForRead(int fd, CB* cb);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Removes the FD and the associated callback from the pollserver.
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   If the callback is registered with other FDs, they will continue
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   to be processed using the callback without modification.
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   If the file-descriptor specified is not registered in the
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   epoll_server, then nothing happens as a result of this call.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - the file-descriptor which should no-longer be monitored.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void UnregisterFD(int fd);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Modifies the event mask for the file-descriptor, replacing
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   the old event_mask with the new one specified here.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   If the file-descriptor specified is not registered in the
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   epoll_server, then nothing happens as a result of this call.
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - the fd whose event mask should be modified.
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   event_mask - the new event mask.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ModifyCallback(int fd, int event_mask);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Modifies the event mask for the file-descriptor such that we
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   no longer request events when 'fd' is readable.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   If the file-descriptor specified is not registered in the
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   epoll_server, then nothing happens as a result of this call.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - the fd whose event mask should be modified.
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void StopRead(int fd);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Modifies the event mask for the file-descriptor such that we
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   request events when 'fd' is readable.
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   If the file-descriptor specified is not registered in the
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   epoll_server, then nothing happens as a result of this call.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - the fd whose event mask should be modified.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void StartRead(int fd);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Modifies the event mask for the file-descriptor such that we
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   no longer request events when 'fd' is writable.
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   If the file-descriptor specified is not registered in the
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   epoll_server, then nothing happens as a result of this call.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - the fd whose event mask should be modified.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void StopWrite(int fd);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Modifies the event mask for the file-descriptor such that we
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   request events when 'fd' is writable.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   If the file-descriptor specified is not registered in the
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   epoll_server, then nothing happens as a result of this call.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - the fd whose event mask should be modified.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void StartWrite(int fd);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Looks up the callback associated with the file-desriptor 'fd'.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   If a callback is associated with this file-descriptor, then
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   it's OnEvent() method is called with the file-descriptor 'fd',
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   and event_mask 'event_mask'
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   If no callback is registered for this file-descriptor, nothing
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   will happen as a result of this call.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   This function is used internally by the EpollServer, but is
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   available publically so that events might be 'faked'. Calling
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   this function with an fd and event_mask is equivalent (as far
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   as the callback is concerned) to having a real event generated
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   by epoll (except, of course, that read(), etc won't necessarily
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   be able to read anything)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - the file-descriptor on which an event has occured.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   event_mask - a bitmask representing the events which have occured
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                on/for this fd. This bitmask is composed of
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                POLLIN, POLLOUT, etc.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleEvent(int fd, int event_mask);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Call this when you want the pollserver to
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   wait for events and execute the callbacks associated with
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   the file-descriptors on which those events have occured.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Depending on the value of timeout_in_us_, this may or may
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   not return immediately. Please reference the set_timeout()
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   function for the specific behaviour.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void WaitForEventsAndExecuteCallbacks();
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   When an fd is registered to use edge trigger notification, the ready
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   list can be used to simulate level trigger semantics. Edge trigger
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   registration doesn't send an initial event, and only rising edge (going
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   from blocked to unblocked) events are sent. A callback can put itself on
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   the ready list by calling SetFDReady() after calling RegisterFD(). The
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   OnEvent method of all callbacks associated with the fds on the ready
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   list will be called immediately after processing the events returned by
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   epoll_wait(). The fd is removed from the ready list before the
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   callback's OnEvent() method is invoked. To stay on the ready list, the
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   OnEvent() (or some function in that call chain) must call SetFDReady
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   again. When a fd is unregistered using UnregisterFD(), the fd is
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   automatically removed from the ready list.
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   When the callback for a edge triggered fd hits the falling edge (about
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   to block, either because of it got an EAGAIN, or had a short read/write
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   operation), it should remove itself from the ready list using
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   SetFDNotReady() (since OnEvent cannot distinguish between invocation
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   from the ready list vs from a normal epoll event). All four ready list
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   methods are safe to be called  within the context of the callbacks.
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Since the ready list invokes EpollCallbackInterface::OnEvent, only fds
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   that are registered with the EpollServer will be put on the ready list.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   SetFDReady() and SetFDNotReady() will do nothing if the EpollServer
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   doesn't know about the fd passed in.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Since the ready list cannot reliably determine proper set of events
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   which should be sent to the callback, SetFDReady() requests the caller
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   to provide the ready list with the event mask, which will be used later
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   when OnEvent() is invoked by the ready list. Hence, the event_mask
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   passedto SetFDReady() does not affect the actual epoll registration of
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   the fd with the kernel. If a fd is already put on the ready list, and
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   SetFDReady() is called again for that fd with a different event_mask,
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   the event_mask will be updated.
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetFDReady(int fd, int events_to_fake);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetFDNotReady(int fd);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   IsFDReady(), ReadyListSize(), and VerifyReadyList are intended as
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   debugging tools and for writing unit tests.
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   ISFDReady() returns whether a fd is in the ready list.
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   ReadyListSize() returns the number of fds on the ready list.
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   VerifyReadyList() checks the consistency of internal data structure. It
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   will CHECK if it finds an error.
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsFDReady(int fd) const;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t ReadyListSize() const { return ready_list_size_; }
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void VerifyReadyList() const;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Registers an alarm 'ac' to go off at time 'timeout_time_in_us'.
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   If the callback returns a positive number from its OnAlarm() function,
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   then the callback will be re-registered at that time, else the alarm
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   owner is responsible for freeing up memory.
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Important: A give AlarmCB* can not be registered again if it is already
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    registered. If a user wants to register a callback again it should first
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    unregister the previous callback before calling RegisterAlarm again.
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   timeout_time_in_us - the absolute time at which the alarm should go off
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   ac - the alarm which will be called.
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RegisterAlarm(int64 timeout_time_in_us, AlarmCB* ac);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Registers an alarm 'ac' to go off at time: (ApproximateNowInUs() +
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   delta_in_us). While this is somewhat less accurate (see the description
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   for ApproximateNowInUs() to see how 'approximate'), the error is never
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   worse than the amount of time it takes to process all events in one
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   WaitForEvents.  As with 'RegisterAlarm()', if the callback returns a
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   positive number from its OnAlarm() function, then the callback will be
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   re-registered at that time, else the alarm owner is responsible for
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   freeing up memory.
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Note that this function is purely a convienence. The
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   same thing may be accomplished by using RegisterAlarm with
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   ApproximateNowInUs() directly.
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Important: A give AlarmCB* can not be registered again if it is already
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    registered. If a user wants to register a callback again it should first
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    unregister the previous callback before calling RegisterAlarm again.
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   delta_in_us - the delta in microseconds from the ApproximateTimeInUs() at
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                 which point the alarm should go off.
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   ac - the alarm which will be called.
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RegisterAlarmApproximateDelta(int64 delta_in_us, AlarmCB* ac) {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RegisterAlarm(ApproximateNowInUsec() + delta_in_us, ac);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Unregister  the alarm referred to by iterator_token; Callers should
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   be warned that a token may have become already invalid when OnAlarm()
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   is called, was unregistered, or OnShutdown was called on that alarm.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    iterator_token - iterator to the alarm callback to unregister.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void UnregisterAlarm(
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const EpollServer::AlarmRegToken& iterator_token);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   returns the number of file-descriptors registered in this EpollServer.
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns:
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   number of FDs registered (discounting the internal pipe used for Wake)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int NumFDsRegistered() const;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Force the epoll server to wake up (by writing to an internal pipe).
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Wake();
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Wrapper around WallTimer's NowInUsec.  We do this so that we can test
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   EpollServer without using the system clock (and can avoid the flakiness
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   that would ensue)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns:
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   the current time as number of microseconds since the Unix epoch.
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int64 NowInUsec() const;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Since calling NowInUsec() many thousands of times per
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   WaitForEventsAndExecuteCallbacks function call is, to say the least,
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   inefficient, we allow users to use an approximate time instead. The
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   time returned from this function is as accurate as NowInUsec() when
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   WaitForEventsAndExecuteCallbacks is not an ancestor of the caller's
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   callstack.
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   However, when WaitForEventsAndExecuteCallbacks -is- an ancestor, then
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   this function returns the time at which the
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   WaitForEventsAndExecuteCallbacks function started to process events or
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   alarms.
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Essentially, this function makes available a fast and mostly accurate
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   mechanism for getting the time for any function handling an event or
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   alarm. When functions which are not handling callbacks or alarms call
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   this function, they get the slow and "absolutely" accurate time.
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Users should be encouraged to use this function.
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns:
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   the "approximate" current time as number of microseconds since the Unix
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   epoch.
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int64 ApproximateNowInUsec() const;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static std::string EventMaskToString(int event_mask);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Logs the state of the epoll server with LOG(ERROR).
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void LogStateOnCrash();
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Set the timeout to the value specified.
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   If the timeout is set to a negative number,
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      WaitForEventsAndExecuteCallbacks() will only return when an event has
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      occured
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   If the timeout is set to zero,
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      WaitForEventsAndExecuteCallbacks() will return immediately
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   If the timeout is set to a positive number,
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      WaitForEventsAndExecuteCallbacks() will return when an event has
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      occured, or when timeout_in_us microseconds has elapsed, whichever
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      is first.
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  Args:
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    timeout_in_us - value specified depending on behaviour desired.
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                    See above.
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_timeout_in_us(int64 timeout_in_us) {
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    timeout_in_us_ = timeout_in_us;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Accessor for the current value of timeout_in_us.
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int timeout_in_us() const { return timeout_in_us_; }
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true when the EpollServer() is being destroyed.
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool in_shutdown() const { return in_shutdown_; }
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ContainsAlarm(EpollAlarmCallbackInterface* alarm) const {
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return all_alarms_.find(alarm) != all_alarms_.end();
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   A function for implementing the ready list. It invokes OnEvent for each
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   of the fd in the ready list, and takes care of adding them back to the
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   ready list if the callback requests it (by checking that out_ready_mask
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   is non-zero).
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CallReadyListCallbacks();
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetFlags(int fd);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline int SetFlags(int fd, int flags) {
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetNonblocking(int fd);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This exists here so that we can override this function in unittests
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in order to make effective mock EpollServer objects.
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int epoll_wait_impl(int epfd,
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              struct epoll_event* events,
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int max_events,
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int timeout_in_ms);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this struct is used internally, and is never used by anything external
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to this class. Some of its members are declared mutable to get around the
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // restriction imposed by hash_set. Since hash_set knows nothing about the
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // objects it stores, it has to assume that every bit of the object is used
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the hash function and equal_to comparison. Thus hash_set::iterator is a
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // const iterator. In this case, the only thing that must stay constant is
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fd. Everything else are just along for the ride and changing them doesn't
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // compromise the hash_set integrity.
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct CBAndEventMask {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CBAndEventMask()
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : cb(NULL),
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          fd(-1),
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          event_mask(0),
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          events_asserted(0),
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          events_to_fake(0),
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          in_use(false) {
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry.le_next = NULL;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry.le_prev = NULL;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CBAndEventMask(EpollCallbackInterface* cb,
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   int event_mask,
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   int fd)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : cb(cb), fd(fd), event_mask(event_mask), events_asserted(0),
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          events_to_fake(0), in_use(false) {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry.le_next = NULL;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry.le_prev = NULL;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Required operator for hash_set. Normally operator== should be a free
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // standing function. However, since CBAndEventMask is a protected type and
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // it will never be a base class, it makes no difference.
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool operator==(const CBAndEventMask& cb_and_mask) const {
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return fd == cb_and_mask.fd;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A callback. If the fd is unregistered inside the callchain of OnEvent,
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the cb will be set to NULL.
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mutable EpollCallbackInterface* cb;
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mutable LIST_ENTRY(CBAndEventMask) entry;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // file descriptor registered with the epoll server.
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int fd;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the current event_mask registered for this callback.
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mutable int event_mask;
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the event_mask that was returned by epoll
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mutable int events_asserted;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the event_mask for the ready list to use to call OnEvent.
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mutable int events_to_fake;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // toggle around calls to OnEvent to tell UnregisterFD to not erase the
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // iterator because HandleEvent is using it.
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mutable bool in_use;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Custom hash function to be used by hash_set.
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct CBAndEventMaskHash {
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t operator()(const CBAndEventMask& cb_and_eventmask) const {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return static_cast<size_t>(cb_and_eventmask.fd);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  typedef base::hash_set<CBAndEventMask, CBAndEventMaskHash> FDToCBMap;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the following four functions are OS-specific, and are likely
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to be changed in a subclass if the poll/select method is changed
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from epoll.
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Deletes a file-descriptor from the set of FDs that should be
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   monitored with epoll.
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Note that this only deals with modifying data relating -directly-
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   with the epoll call-- it does not modify any data within the
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   epoll_server.
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - the file descriptor to-be-removed from the monitoring set
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DelFD(int fd) const;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Adds a file-descriptor to the set of FDs that should be
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   monitored with epoll.
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Note that this only deals with modifying data relating -directly-
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   with the epoll call.
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - the file descriptor to-be-added to the monitoring set
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   event_mask - the event mask (consisting of EPOLLIN, EPOLLOUT, etc
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                 OR'd together) which will be associated with this
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                 FD initially.
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddFD(int fd, int event_mask) const;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Modifies a file-descriptor in the set of FDs that should be
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   monitored with epoll.
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Note that this only deals with modifying data relating -directly-
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   with the epoll call.
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - the file descriptor to-be-added to the monitoring set
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   event_mask - the event mask (consisting of EPOLLIN, EPOLLOUT, etc
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                 OR'd together) which will be associated with this
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                 FD after this call.
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ModFD(int fd, int event_mask) const;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Modified the event mask associated with an FD in the set of
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   data needed by epoll.
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Events are removed before they are added, thus, if ~0 is put
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   in 'remove_event', whatever is put in 'add_event' will be
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   the new event mask.
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   If the file-descriptor specified is not registered in the
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   epoll_server, then nothing happens as a result of this call.
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd - the file descriptor whose event mask is to be modified
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   remove_event - the events which are to be removed from the current
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                  event_mask
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   add_event - the events which are to be added to the current event_mask
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ModifyFD(int fd, int remove_event, int add_event);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ////////////////////////////////////////
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Waits for events, and calls HandleEvents() for each
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   fd, event pair discovered to possibly have an event.
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Note that a callback (B) may get a spurious event if
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   another callback (A) has closed a file-descriptor N, and
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   the callback (B) has a newly opened file-descriptor, which
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   also happens to be N.
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void WaitForEventsAndCallHandleEvents(int64 timeout_in_us,
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                struct epoll_event events[],
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                int events_size);
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   An internal function for implementing the ready list. It adds a fd's
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   CBAndEventMask to the ready list. If the fd is already on the ready
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   list, it is a no-op.
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddToReadyList(CBAndEventMask* cb_and_mask);
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   An internal function for implementing the ready list. It remove a fd's
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   CBAndEventMask from the ready list. If the fd is not on the ready list,
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   it is a no-op.
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RemoveFromReadyList(const CBAndEventMask& cb_and_mask);
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Calls any pending alarms that should go off and reregisters them if they
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // were recurring.
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void CallAndReregisterAlarmEvents();
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The file-descriptor created for epolling
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int epoll_fd_;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The mapping of file-descriptor to CBAndEventMasks
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FDToCBMap cb_map_;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Custom hash function to be used by hash_set.
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct AlarmCBHash {
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t operator()(AlarmCB*const& p) const {
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return reinterpret_cast<size_t>(p);
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TOOD(sushantj): Having this hash_set is avoidable. We currently have it
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // only so that we can enforce stringent checks that a caller can not register
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the same alarm twice. One option is to have an implementation in which
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this hash_set is used only in the debug mode.
677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  typedef base::hash_set<AlarmCB*, AlarmCBHash> AlarmCBMap;
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AlarmCBMap all_alarms_;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeToAlarmCBMap alarm_map_;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The amount of time in microseconds that we'll wait before returning
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from the WaitForEventsAndExecuteCallbacks() function.
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If this is positive, wait that many microseconds.
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If this is negative, wait forever, or for the first event that occurs
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If this is zero, never wait for an event.
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 timeout_in_us_;
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is nonzero only after the invocation of epoll_wait_impl within
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WaitForEventsAndCallHandleEvents and before the function
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WaitForEventsAndExecuteCallbacks returns.  At all other times, this is
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // zero. This enables us to have relatively accurate time returned from the
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ApproximateNowInUs() function. See that function for more details.
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 recorded_now_in_us_;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is used to implement CallAndReregisterAlarmEvents. This stores
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // all alarms that were reregistered because OnAlarm() returned a
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // value > 0 and the time at which they should be executed is less that
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the current time.  By storing such alarms in this map we ensure
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that while calling CallAndReregisterAlarmEvents we do not call
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnAlarm on any alarm in this set. This ensures that we do not
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // go in an infinite loop.
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AlarmCBMap alarms_reregistered_and_should_be_skipped_;
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_HEAD(ReadyList, CBAndEventMask) ready_list_;
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LIST_HEAD(TmpList, CBAndEventMask) tmp_list_;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ready_list_size_;
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(alyssar): make this into something that scales up.
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int events_size_ = 256;
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct epoll_event events_[256];
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef EPOLL_SERVER_EVENT_TRACING
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct EventRecorder {
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EventRecorder() : num_records_(0), record_threshold_(10000) {}
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~EventRecorder() {
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Clear();
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // When a number of events equals the record threshold,
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the collected data summary for all FDs will be written
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to LOG(INFO). Note that this does not include the
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // individual events (if you'reinterested in those, you'll
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // have to get at them programmatically).
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // After any such flushing to LOG(INFO) all events will
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // be cleared.
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that the definition of an 'event' is a bit 'hazy',
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // as it includes the 'Unregistration' event, and perhaps
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // others.
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void set_record_threshold(int64 new_threshold) {
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      record_threshold_ = new_threshold;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void Clear() {
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int i = 0; i < debug_events_.size(); ++i) {
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delete debug_events_[i];
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      debug_events_.clear();
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unregistered_fds_.clear();
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_counts_.clear();
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void MaybeRecordAndClear() {
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++num_records_;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((num_records_ > record_threshold_) &&
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (record_threshold_ > 0)) {
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(INFO) << "\n" << *this;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_records_ = 0;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Clear();
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void RecordFDMaskEvent(int fd, int mask, const char* function) {
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FDMaskOutput* fdmo = new FDMaskOutput(fd, mask, function);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      debug_events_.push_back(fdmo);
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MaybeRecordAndClear();
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void RecordEpollWaitEvent(int timeout_in_ms,
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int num_events_generated) {
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EpollWaitOutput* ewo = new EpollWaitOutput(timeout_in_ms,
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  num_events_generated);
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      debug_events_.push_back(ewo);
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MaybeRecordAndClear();
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void RecordEpollEvent(int fd, int event_mask) {
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Events& events_for_fd = event_counts_[fd];
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      events_for_fd.AssignFromMask(event_mask);
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MaybeRecordAndClear();
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    friend ostream& operator<<(ostream& os, const EventRecorder& er) {
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int i = 0; i < er.unregistered_fds_.size(); ++i) {
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        os << "fd: " << er.unregistered_fds_[i] << "\n";
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        os << er.unregistered_fds_[i];
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (EventCountsMap::const_iterator i = er.event_counts_.begin();
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           i != er.event_counts_.end();
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           ++i) {
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        os << "fd: " << i->first << "\n";
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        os << i->second;
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int i = 0; i < er.debug_events_.size(); ++i) {
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        os << *(er.debug_events_[i]) << "\n";
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return os;
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void RecordUnregistration(int fd) {
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EventCountsMap::iterator i = event_counts_.find(fd);
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i != event_counts_.end()) {
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        unregistered_fds_.push_back(i->second);
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        event_counts_.erase(i);
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MaybeRecordAndClear();
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   protected:
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    class DebugOutput {
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     public:
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      friend ostream& operator<<(ostream& os, const DebugOutput& debug_output) {
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        debug_output.OutputToStream(os);
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return os;
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      virtual void OutputToStream(ostream* os) const = 0;
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      virtual ~DebugOutput() {}
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    class FDMaskOutput : public DebugOutput {
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     public:
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FDMaskOutput(int fd, int mask, const char* function) :
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          fd_(fd), mask_(mask), function_(function) {}
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      virtual void OutputToStream(ostream* os) const {
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*os) << "func: " << function_
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << "\tfd: " << fd_;
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (mask_ != 0) {
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           (*os) << "\tmask: " << EventMaskToString(mask_);
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int fd_;
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int mask_;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const char* function_;
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    class EpollWaitOutput : public DebugOutput {
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     public:
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EpollWaitOutput(int timeout_in_ms,
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      int num_events_generated) :
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          timeout_in_ms_(timeout_in_ms),
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          num_events_generated_(num_events_generated) {}
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      virtual void OutputToStream(ostream* os) const {
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*os) << "timeout_in_ms: " << timeout_in_ms_
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << "\tnum_events_generated: " << num_events_generated_;
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     protected:
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int timeout_in_ms_;
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int num_events_generated_;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct Events {
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Events() :
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          epoll_in(0),
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          epoll_pri(0),
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          epoll_out(0),
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          epoll_rdnorm(0),
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          epoll_rdband(0),
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          epoll_wrnorm(0),
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          epoll_wrband(0),
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          epoll_msg(0),
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          epoll_err(0),
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          epoll_hup(0),
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          epoll_oneshot(0),
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          epoll_et(0) {}
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      void AssignFromMask(int event_mask) {
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (event_mask & EPOLLIN) ++epoll_in;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (event_mask & EPOLLPRI) ++epoll_pri;
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (event_mask & EPOLLOUT) ++epoll_out;
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (event_mask & EPOLLRDNORM) ++epoll_rdnorm;
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (event_mask & EPOLLRDBAND) ++epoll_rdband;
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (event_mask & EPOLLWRNORM) ++epoll_wrnorm;
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (event_mask & EPOLLWRBAND) ++epoll_wrband;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (event_mask & EPOLLMSG) ++epoll_msg;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (event_mask & EPOLLERR) ++epoll_err;
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (event_mask & EPOLLHUP) ++epoll_hup;
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (event_mask & EPOLLONESHOT) ++epoll_oneshot;
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (event_mask & EPOLLET) ++epoll_et;
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      };
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      friend ostream& operator<<(ostream& os, const Events& ev) {
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ev.epoll_in) {
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          os << "\t      EPOLLIN: " << ev.epoll_in << "\n";
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ev.epoll_pri) {
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          os << "\t     EPOLLPRI: " << ev.epoll_pri << "\n";
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ev.epoll_out) {
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          os << "\t     EPOLLOUT: " << ev.epoll_out << "\n";
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ev.epoll_rdnorm) {
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          os << "\t  EPOLLRDNORM: " << ev.epoll_rdnorm << "\n";
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ev.epoll_rdband) {
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          os << "\t  EPOLLRDBAND: " << ev.epoll_rdband << "\n";
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ev.epoll_wrnorm) {
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          os << "\t  EPOLLWRNORM: " << ev.epoll_wrnorm << "\n";
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ev.epoll_wrband) {
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          os << "\t  EPOLLWRBAND: " << ev.epoll_wrband << "\n";
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ev.epoll_msg) {
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          os << "\t     EPOLLMSG: " << ev.epoll_msg << "\n";
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ev.epoll_err) {
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          os << "\t     EPOLLERR: " << ev.epoll_err << "\n";
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ev.epoll_hup) {
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          os << "\t     EPOLLHUP: " << ev.epoll_hup << "\n";
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ev.epoll_oneshot) {
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          os << "\t EPOLLONESHOT: " << ev.epoll_oneshot << "\n";
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ev.epoll_et) {
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          os << "\t      EPOLLET: " << ev.epoll_et << "\n";
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return os;
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int epoll_in;
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int epoll_pri;
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int epoll_out;
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int epoll_rdnorm;
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int epoll_rdband;
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int epoll_wrnorm;
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int epoll_wrband;
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int epoll_msg;
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int epoll_err;
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int epoll_hup;
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int epoll_oneshot;
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int epoll_et;
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<DebugOutput*> debug_events_;
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<Events> unregistered_fds_;
928c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    typedef base::hash_map<int, Events> EventCountsMap;
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EventCountsMap event_counts_;
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 num_records_;
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 record_threshold_;
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ClearEventRecords() {
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_recorder_.Clear();
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WriteEventRecords(ostream* os) const {
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*os) << event_recorder_;
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable EventRecorder event_recorder_;
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper functions used in the destructor.
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CleanupFDToCBMap();
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CleanupTimeToAlarmCBMap();
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The callback registered to the fds below.  As the purpose of their
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // registration is to wake the epoll server it just clears the pipe and
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returns.
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ReadPipeCallback> wake_cb_;
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A pipe owned by the epoll server.  The server will be registered to listen
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on read_fd_ and can be woken by Wake() which writes to write_fd_.
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int read_fd_;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int write_fd_;
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This boolean is checked to see if it is false at the top of the
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WaitForEventsAndExecuteCallbacks function. If not, then it either returns
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // without doing work, and logs to ERROR, or aborts the program (in
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DEBUG mode). If so, then it sets the bool to true, does work, and
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sets it back to false when done. This catches unwanted recursion.
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool in_wait_for_events_and_execute_callbacks_;
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true when the EpollServer() is being destroyed.
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool in_shutdown_;
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(EpollServer);
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class EpollAlarmCallbackInterface {
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Called when an alarm times out. Invalidates an AlarmRegToken.
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   WARNING: If a token was saved to refer to an alarm callback, OnAlarm must
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   delete it, as the reference is no longer valid.
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns:
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   the unix time (in microseconds) at which this alarm should be signaled
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   again, or 0 if the alarm should be removed.
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int64 OnAlarm() = 0;
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Called when the an alarm is registered. Invalidates an AlarmRegToken.
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Args:
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   token: the iterator to the the alarm registered in the alarm map.
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   WARNING: this token becomes invalid when the alarm fires, is
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   unregistered, or OnShutdown is called on that alarm.
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   eps: the epoll server the alarm is registered with.
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnRegistration(const EpollServer::AlarmRegToken& token,
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              EpollServer* eps) = 0;
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Called when the an alarm is unregistered.
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   WARNING: It is not valid to unregister a callback and then use the token
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   that was saved to refer to the callback.
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnUnregistration() = 0;
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Summary:
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Called when the epoll server is shutting down.
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   Invalidates the AlarmRegToken that was given when this alarm was
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   registered.
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnShutdown(EpollServer* eps) = 0;
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~EpollAlarmCallbackInterface() {}
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EpollAlarmCallbackInterface() {}
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A simple alarm which unregisters itself on destruction.
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PLEASE NOTE:
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Any classes overriding these functions must either call the implementation
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the parent class, or is must otherwise make sure that the 'registered_'
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// boolean and the token, 'token_', are updated appropriately.
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class EpollAlarm : public EpollAlarmCallbackInterface {
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EpollAlarm();
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~EpollAlarm();
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Marks the alarm as unregistered and returns 0.  The return value may be
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // safely ignored by subclasses.
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int64 OnAlarm() OVERRIDE;
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Marks the alarm as registered, and stores the token.
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnRegistration(const EpollServer::AlarmRegToken& token,
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              EpollServer* eps) OVERRIDE;
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Marks the alarm as unregistered.
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnUnregistration() OVERRIDE;
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Marks the alarm as unregistered.
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnShutdown(EpollServer* eps) OVERRIDE;
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the alarm was registered, unregister it.
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UnregisterIfRegistered();
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool registered() const { return registered_; }
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const EpollServer* eps() const { return eps_; }
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EpollServer::AlarmRegToken token_;
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EpollServer* eps_;
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool registered_;
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif  // NET_TOOLS_EPOLL_SERVER_EPOLL_SERVER_H_
1054