#include <XmlRpcDispatch.h>
Public Types | |
enum | EventType { ReadableEvent = 1, WritableEvent = 2, Exception = 4 } |
Values indicating the type of events a source is interested in. More... | |
Public Member Functions | |
XmlRpcDispatch () | |
Constructor. | |
~XmlRpcDispatch () | |
void | addSource (XmlRpcSource *source, unsigned eventMask) |
Monitor this source for the event types specified by the event mask and call its event handler when any of the events occur. | |
void | removeSource (XmlRpcSource *source) |
Stop monitoring this source. | |
void | setSourceEvents (XmlRpcSource *source, unsigned eventMask) |
Modify the types of events to watch for on this source. | |
void | work (double msTime) |
Watch current set of sources and process events for the specified duration (in ms, -1 implies wait forever, or until exit is called). | |
void | exit () |
Exit from work routine. | |
void | clear () |
Clear all sources from the monitored sources list. Sources are closed. | |
Protected Types | |
typedef std::list < MonitoredSource > | SourceList |
Protected Member Functions | |
bool | waitForAndProcessEvents (double timeout) |
Wait for I/O on any source, timeout, or interrupt signal. | |
double | getTime () |
Protected Attributes | |
SourceList | _sources |
double | _endTime |
bool | _doClear |
bool | _inWork |
Classes | |
struct | MonitoredSource |
typedef std::list< MonitoredSource > XmlRpc::XmlRpcDispatch::SourceList [protected] |
Values indicating the type of events a source is interested in.
ReadableEvent | data available to read |
WritableEvent | connected/data can be written without blocking |
Exception | uh oh |
00029 { 00030 ReadableEvent = 1, 00031 WritableEvent = 2, 00032 Exception = 4 00033 };
XmlRpcDispatch::XmlRpcDispatch | ( | ) |
void XmlRpcDispatch::addSource | ( | XmlRpcSource * | source, | |
unsigned | eventMask | |||
) |
void XmlRpcDispatch::removeSource | ( | XmlRpcSource * | source | ) |
void XmlRpcDispatch::setSourceEvents | ( | XmlRpcSource * | source, | |
unsigned | eventMask | |||
) |
void XmlRpcDispatch::work | ( | double | msTime | ) |
Watch current set of sources and process events for the specified duration (in ms, -1 implies wait forever, or until exit is called).
00076 { 00077 // Compute end time 00078 double timeNow = getTime(); 00079 _endTime = (timeout < 0.0) ? -1.0 : (timeNow + timeout); 00080 _doClear = false; 00081 _inWork = true; 00082 00083 // Only work while there is something to monitor 00084 while (_sources.size() > 0) { 00085 00086 // Wait for and dispatch events 00087 if ( ! waitForAndProcessEvents(timeout)) 00088 { 00089 _inWork = false; 00090 return; 00091 } 00092 00093 00094 // Check whether to clear all sources 00095 if (_doClear) 00096 { 00097 SourceList closeList = _sources; 00098 _sources.clear(); 00099 for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) { 00100 XmlRpcSource *src = it->getSource(); 00101 src->close(); 00102 } 00103 00104 _doClear = false; 00105 } 00106 00107 // Check whether end time has passed or exit has been called 00108 if (_endTime == 0.0) // Exit 00109 break; 00110 else if (_endTime > 0.0) // Check for timeout 00111 { 00112 double t = getTime(); 00113 if (t > _endTime) 00114 break; 00115 00116 // Decrement timeout by elapsed time 00117 timeout -= (t - timeNow); 00118 if (timeout < 0.0) 00119 timeout = 0.0; // Shouldn't happen but its fp math... 00120 timeNow = t; 00121 } 00122 } 00123 00124 _inWork = false; 00125 }
void XmlRpcDispatch::exit | ( | ) |
void XmlRpcDispatch::clear | ( | ) |
Clear all sources from the monitored sources list. Sources are closed.
00141 { 00142 if (_inWork) 00143 _doClear = true; // Finish reporting current events before clearing 00144 else 00145 { 00146 SourceList closeList = _sources; 00147 _sources.clear(); 00148 for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) 00149 it->getSource()->close(); 00150 } 00151 }
bool XmlRpcDispatch::waitForAndProcessEvents | ( | double | timeout | ) | [protected] |
Wait for I/O on any source, timeout, or interrupt signal.
00177 { 00178 #if defined(_WINDOWS) && 0 00179 00180 int nHandles = 0; 00181 SourceList::iterator it; 00182 for (it=_sources.begin(); it!=_sources.end(); ++it) { 00183 int fd = it->getSource()->getfd(); 00184 int mask = 0; 00185 if (it->getMask() & ReadableEvent) mask = (FD_READ | FD_CLOSE | FD_ACCEPT); 00186 if (it->getMask() & WritableEvent) mask |= (FD_WRITE | FD_CLOSE); 00187 00188 #else // Posix 00189 00190 // Construct the sets of descriptors we are interested in 00191 fd_set inFd, outFd, excFd; 00192 FD_ZERO(&inFd); 00193 FD_ZERO(&outFd); 00194 FD_ZERO(&excFd); 00195 00196 int maxFd = -1; 00197 SourceList::iterator it; 00198 for (it=_sources.begin(); it!=_sources.end(); ++it) { 00199 int fd = it->getSource()->getfd(); 00200 if (it->getMask() & ReadableEvent) FD_SET(fd, &inFd); 00201 if (it->getMask() & WritableEvent) FD_SET(fd, &outFd); 00202 if (it->getMask() & Exception) FD_SET(fd, &excFd); 00203 if (it->getMask() && fd > maxFd) maxFd = fd; 00204 } 00205 00206 // Check for events 00207 int nEvents; 00208 if (_endTime < 0.0) 00209 nEvents = select(maxFd+1, &inFd, &outFd, &excFd, NULL); 00210 else 00211 { 00212 struct timeval tv; 00213 tv.tv_sec = (int)floor(timeout); 00214 tv.tv_usec = ((int)floor(1000000.0 * (timeout-floor(timeout)))) % 1000000; 00215 nEvents = select(maxFd+1, &inFd, &outFd, &excFd, &tv); 00216 } 00217 00218 if (nEvents < 0 && errno != EINTR) 00219 { 00220 XmlRpcUtil::error("Error in XmlRpcDispatch::work: error in select (%d).", nEvents); 00221 return false; 00222 } 00223 00224 // Process events 00225 for (it=_sources.begin(); it != _sources.end(); ) 00226 { 00227 SourceList::iterator thisIt = it++; 00228 XmlRpcSource* src = thisIt->getSource(); 00229 int fd = src->getfd(); 00230 00231 if (fd <= maxFd) { 00232 // handleEvent is called once per event type signalled 00233 unsigned newMask = 0; 00234 int nset = 0; 00235 if (FD_ISSET(fd, &inFd)) 00236 { 00237 newMask |= src->handleEvent(ReadableEvent); 00238 ++nset; 00239 } 00240 if (FD_ISSET(fd, &outFd)) 00241 { 00242 newMask |= src->handleEvent(WritableEvent); 00243 ++nset; 00244 } 00245 if (FD_ISSET(fd, &excFd)) 00246 { 00247 newMask |= src->handleEvent(Exception); 00248 ++nset; 00249 } 00250 00251 // Some event occurred 00252 if (nset) 00253 { 00254 if (newMask) 00255 thisIt->getMask() = newMask; 00256 else // Stop monitoring this one 00257 { 00258 _sources.erase(thisIt); 00259 if ( ! src->getKeepOpen()) 00260 src->close(); 00261 } 00262 } 00263 } 00264 } 00265 #endif 00266 00267 return true; 00268 }
double XmlRpcDispatch::getTime | ( | ) | [protected] |
00157 { 00158 #ifdef USE_FTIME 00159 struct timeb tbuff; 00160 00161 ftime(&tbuff); 00162 return ((double) tbuff.time + ((double)tbuff.millitm / 1000.0) + 00163 ((double) tbuff.timezone * 60)); 00164 #else 00165 struct timeval tv; 00166 struct timezone tz; 00167 00168 gettimeofday(&tv, &tz); 00169 return (tv.tv_sec + tv.tv_usec / 1000000.0); 00170 #endif /* USE_FTIME */ 00171 }
SourceList XmlRpc::XmlRpcDispatch::_sources [protected] |
double XmlRpc::XmlRpcDispatch::_endTime [protected] |
bool XmlRpc::XmlRpcDispatch::_doClear [protected] |
bool XmlRpc::XmlRpcDispatch::_inWork [protected] |