/* * Copyright 2011 Steven Gribble * * This file is part of the UW CSE 333 course project sequence * (333proj). * * 333proj is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * 333proj is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 333proj. If not, see . */ #ifndef _HW4_EVENTLOOP_H_ #define _HW4_EVENTLOOP_H_ #include #include #include #include "./EventLoopHandler.h" namespace hw4 { // An EventLoop object captures a thread of execution and uses the // Linux poll system call ("man 3 poll") to receive and dispatch // events on registered file descriptors to EventLoopHandler objects. class EventLoop { public: // The following bitmasks define the kinds of file descriptor events // that an EventLoop can deliver. You can register interest in any // combination of these events using RegisterFD, and when a covered // event fires, the EventLoop will invoke your HandleEvent() method // indicating what event or events have fired. For example, to // register interest in FD_IS_READABLE, FD_ERR, and FD_HUP, you // would pass in an integer like: // // unsigned int events = EventLoop::FD_IS_READABLE | // EventLoop::FD_ERR | // EventLoop::FD_HUP; enum eventtypes { FD_IS_READABLE = (1 << 0), // fd is ready to read FD_IS_WRITEABLE = (1 << 1), // fd is ready to write FD_ERR = (1 << 2), // an error happened on fd FD_HUP = (1 << 3) // the remote party disconnected }; // Constructors / destructor. EventLoop(); ~EventLoop(); // Register interest in receiving the events indicated in the bitfield // "events" on file descriptor "fd". Whenever one of the indicated // events fires, EventLoop will invoke eh.handle, passing in fd and a // unsigned int bitfield showing which events happened. If the // handler returns false, the event loop will invoke "delete" on the // handler. // // Returns true on success, false on error. The only error case is // if "fd" is not a valid file descriptor. bool RegisterFD(const int fd, const unsigned int events, EventLoopHandler *eh); // Unregister interest in receiving any events on "fd." Returns // true on success, false on error. The only error case is if fd is // not currently registered. Does not call "delete" on the handler. bool UnregisterFD(const int fd); // Begin processing events. This method captures the caller's thread // to power the event loop. Run() returns if there are ever no more // registered fds. void Run(); // Event handlers can invoke this function to tell the event loop // to return out of its loop. void Quit(); private: // This private helper function updates the fds_ structure // if new registrations have arrived. void UpdateFDS(void); // We use this structure to store an fd registration. typedef struct { int fd; // the fd that was registered unsigned int events; // the events of interest EventLoopHandler *eh; // the event handler object to call } Registration; // This is the struct pollfd array we pass to the poll // system call. As file descriptors are added to it, // we may need to dynamically resize it. struct pollfd *fds_; // This is the size of the pollfd array; this represents the total // allocated capacity of the array, not the number of fds currently // stored in it. As the capacity is exhausted, we resize it. unsigned int fds_size_; // This map stores the set of file descriptors and associated // EventLoop::Registration objects that have been registered. std::map fd_registrations_; // This list stores the set of event handlers that have been // unregistered during the last iteration through. std::list fd_deregistrations_; // This flag tracks whether or not the fd_registrations_ map has // been updated. bool registrations_updated_; // This flag tracks whether or not somebody has called Quit(). bool quit_; }; } // namespace hw4 #endif // _HW4_EVENTLOOP_H_