📄 eventloop.cpp
字号:
//// The contents of this file are subject to the Mozilla Public// License Version 1.1 (the "License"); you may not use this file// except in compliance with the License. You may obtain a copy// of the License at http://www.mozilla.org/MPL/// // Software distributed under the License is distributed on an// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or// implied. See the License for the specific language governing// rights and limitations under the License.// // The Original Code is State Machine Compiler (SMC).// // The Initial Developer of the Original Code is Charles W. Rapp.// Portions created by Charles W. Rapp are// Copyright (C) 2000 - 2007. Charles W. Rapp.// All Rights Reserved.// // Contributor(s): //// Name// Eventloop.h//// Description// Encapsulates the select-based event loop and timer table.//// RCS ID// $Id: Eventloop.cpp,v 1.6 2008/02/04 12:45:07 fperrad Exp $//// CHANGE LOG// $Log: Eventloop.cpp,v $// Revision 1.6 2008/02/04 12:45:07 fperrad// fix build on linux (gcc 4.1.3)//// Revision 1.5 2007/12/28 12:34:40 cwrapp// Version 5.0.1 check-in.//// Revision 1.4 2005/05/28 13:31:18 cwrapp// Updated C++ examples.//// Revision 1.0 2003/12/14 19:35:40 charlesr// Initial revision//#include "Eventloop.h"#include <errno.h>#if !defined(WIN32)#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/time.h>#include <sys/resource.h>#endifconst static long USECS_PER_SEC = 1000000;const static long USECS_PER_MSEC = 1000;const static int WIN32_MAX_SOCKET = 1024;//---------------------------------------------------------------// Eventloop() (Public)// Default constructor.//Eventloop::Eventloop(): _continueRunning(1), _maxFD(-1), _fdCount(0), _timerTable(NULL){#if !defined(WIN32) rlimit limit;#endif FD_ZERO(&_fdSet); // Allocate the file descriptor callback table. First, find // out the max file descriptor value.#if defined(WIN32) _fdTable = new InputListener*[WIN32_MAX_SOCKET]; (void) memset(_fdTable, 0, (FD_SETSIZE * sizeof(InputListener*)));#else (void) getrlimit(RLIMIT_NOFILE, &limit); _fdTable = new InputListener*[limit.rlim_cur]; (void) memset(_fdTable, 0, (limit.rlim_cur * sizeof(InputListener*)));#endif return;} // end of Eventloop::Eventloop()//---------------------------------------------------------------// ~Eventloop() (Public)// Destructor.//Eventloop::~Eventloop(){ Eventloop::Timer *timerIt, *nextTimer; // Just in case the event loop is still running. _continueRunning = 0; if (_fdTable != NULL) { delete[] _fdTable; _fdTable = NULL; } for (timerIt = _timerTable; timerIt != NULL; timerIt = nextTimer) { nextTimer = timerIt->getNext(); timerIt->setNext(NULL); delete timerIt; } return;} // end of Eventloop::~Eventloop()//---------------------------------------------------------------// start() (Public)// Start the event loop running.//int Eventloop::start(){ timeval timeout, currTime, *timeoutPtr; Timer *timer; fd_set readSet; int i, fdCount, retcode; TimerListener *listener; char *timerName; _continueRunning = 1; retcode = 0; while (_continueRunning == 1) { // Figure out how long to wait. If there are no timers, // then set timeoutPtr to NULL and wait forever. // Otherwise, put the timeout in the timeval struct and // point timeoutPtr to it. if (_timerTable == NULL) { timeoutPtr = NULL; } else { // Get the current time and figure out how long until // the next timeout. gettime(currTime); // If we have passed the current timeout value, then // don't sleep at all. if (*_timerTable < currTime) { timeout.tv_sec = 0; timeout.tv_usec = 0; } else { timeout.tv_sec = (_timerTable->getExpiration()).tv_sec - currTime.tv_sec; timeout.tv_usec = (_timerTable->getExpiration()).tv_usec - currTime.tv_usec; // If the microseconds are less than 0, then subtract // a second and add 1,000,000 microseconds. if (timeout.tv_usec < 0) { --(timeout.tv_sec); timeout.tv_usec += USECS_PER_SEC; } } timeoutPtr = &timeout; } // Since select modifies the FD sets, pass in a copy. FD_ZERO(&readSet); for (i = 0; i < _maxFD; ++i) { if (FD_ISSET(i, &_fdSet)) {#if defined(WIN32) FD_SET((u_int) i, &readSet);#else FD_SET(i, &readSet);#endif } } if ((fdCount = select(_maxFD, &readSet, NULL, NULL, timeoutPtr)) < 0) { // If select() was interrupted, ignore the error. if (errno != EINTR) { _continueRunning = 0; retcode = errno; } } else { // Issue read events first. for (i = 0; i < _maxFD && fdCount > 0; ++i) { if (FD_ISSET(i, &readSet)) { --fdCount; if (_fdTable[i] != NULL) { _fdTable[i]->handleReceive(i); } } } // Issue timeouts. gettime(currTime); while (_timerTable != NULL && *_timerTable <= currTime) { // Remove the timer from the timer table *before* // issuing the callback 'cause the callback may // set this same timer again before returning // (and the set will fail if the timer is already // in the table). timer = _timerTable; _timerTable = timer->getNext(); timer->setNext(NULL); // Save away the necessary timer info. listener = &(timer->getListener()); timerName = new char[strlen(timer->getName()) + 1]; strcpy(timerName, timer->getName()); // Now delete the defunct timer. delete timer; listener->handleTimeout(timerName); delete[] timerName; } } } return(retcode);} // end of Eventloop::start()//---------------------------------------------------------------// stop() (Public)// Stop the event loop.//void Eventloop::stop(){ _continueRunning = 0; return;} // end of Eventloop::stop()//---------------------------------------------------------------// addFD(int, InputListener&) (Public)// Start watching a file descriptor and route the callback to the// given connection.//void Eventloop::addFD(int fd, InputListener& listener){ if (!FD_ISSET(fd, &_fdSet)) {#if defined(WIN32) FD_SET((u_int) fd, &_fdSet);#else FD_SET(fd, &_fdSet);#endif ++_fdCount; } _fdTable[fd] = &listener; if (fd >= _maxFD) { _maxFD = fd + 1; } return;} // end of Eventloop::addFD(int, InputListener&)//---------------------------------------------------------------// removeFD(int) (Public)// Stop watching a file descriptor.//void Eventloop::removeFD(int fd){ int i;#if defined(WIN32) FD_CLR((u_int) fd, &_fdSet);#else FD_CLR(fd, &_fdSet);#endif _fdTable[fd] = NULL; --_fdCount; // Are we watching any file descriptors? if (_fdCount == 0) { _maxFD = -1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -