#ifndef __IPollSet_h_ #define __IPollSet_h_ #include #include #include #include "MiscSupport.h" /* * This is a wrapper around the epoll_create(), epoll_wait(), and epoll_ctl() * system calls to make them easier to use. Some items are wrapped in STL * data structures. This also adds common error checking code, which will * send messages to the log and abort as required. * * IPollSet provides the exact same interface and semantics as PollSet. * IPollSet is optimized for cases like our main input thread where we are * listening to a large number of sockets AND the set of sockets does not * change very much between uses. If you are going to use * clearFileDescriptors() after each time that you wait, or if you are going * to create a new one of these object each time you want to wait, then you * should you PollSet, instead of IPollSet, because PollSet is more efficient * in that case. * * This class always uses the level-triggered option. If the system call * wakes you, and you forget to check the socket, and you wait again, the * system call will immediately wake you again. This is the default option * for epoll(), and the only option for poll(). * * Previous revisions of this file said that poll() (and therefor PollSet) was * edge triggered. That documentation was not correct. */ class IPollSet { public: typedef std::set< int > HandleSet; private: int _timeout; HandleSet _woken; std::map< int, int > _actions; /* This points from a handle to the set of * things that we are listening for on that * handle (i.e. read/write/both). */ int _epollHandle; int _eventCount; /* This is the size of the _eventCount array. We only * expand this when the old one overflows. It never * shrinks. */ epoll_event *_events; /* Space for the result. Cache this so we don't have * to ask for dynamic memory each time. */ void loadFromOther(IPollSet const &other); void addAction(int fd, int action); void removeAction(int fd, int action); void createEPollHandle(); void closeEPollHandle(); void createEvents(bool forceBigger); public: IPollSet(); // Cleanup. _events points to dynamic memory. _epollHandle needs to be // released. ~IPollSet(); IPollSet &operator =(IPollSet const &other); IPollSet(IPollSet const &other); // Defaults to none. void setTimeoutNone(); void setTimeoutMs(int timeout); // If the pointer is null, then we disable the timeout. Otherwise we // interpret this like a select call would, with the number of seconds // and microseconds to wait. void setTimeout(timeval const *timeVal); // Defaults to empty. Is only reset when you reset it. void addForRead(int fd); void removeForRead(int fd); void addForWrite(int fd); void removeForWrite(int fd); void clearFileDescriptors(); // Read the current state. Mostly for debugging. bool watchingForRead(int fd); bool watchingForWrite(int fd); // This clears the woken() set, then fills it based on the results of // the poll. Fatal errors are written to the log, then we abort. Non fatal // errors are ignored. This can return with nothing in the woken() set. // This could be a timeout or a signal. void poll(); // These are the file handles which were ready after the most recent call to // poll. HandleSet const &woken() const; }; #endif