Go to the documentation of this file.00001
00002 #include "XmlRpcDispatch.h"
00003 #include "XmlRpcSource.h"
00004 #include "XmlRpcUtil.h"
00005
00006 #include <math.h>
00007 #include <errno.h>
00008 #include <sys/timeb.h>
00009 #if defined (__ANDROID__)
00010 #include <sys/select.h>
00011 #endif
00012
00013 #if defined(_WINDOWS)
00014 # include <winsock2.h>
00015
00016 # define USE_FTIME
00017 # if defined(_MSC_VER)
00018 # define timeb _timeb
00019 # define ftime _ftime_s
00020 # endif
00021 #else
00022 # include <sys/time.h>
00023 #endif // _WINDOWS
00024
00025
00026 using namespace XmlRpc;
00027
00028
00029 XmlRpcDispatch::XmlRpcDispatch()
00030 {
00031 _endTime = -1.0;
00032 _doClear = false;
00033 _inWork = false;
00034 }
00035
00036
00037 XmlRpcDispatch::~XmlRpcDispatch()
00038 {
00039 }
00040
00041
00042
00043 void
00044 XmlRpcDispatch::addSource(XmlRpcSource* source, unsigned mask)
00045 {
00046 _sources.push_back(MonitoredSource(source, mask));
00047 }
00048
00049
00050 void
00051 XmlRpcDispatch::removeSource(XmlRpcSource* source)
00052 {
00053 for (SourceList::iterator it=_sources.begin(); it!=_sources.end(); ++it)
00054 if (it->getSource() == source)
00055 {
00056 _sources.erase(it);
00057 break;
00058 }
00059 }
00060
00061
00062
00063 void
00064 XmlRpcDispatch::setSourceEvents(XmlRpcSource* source, unsigned eventMask)
00065 {
00066 for (SourceList::iterator it=_sources.begin(); it!=_sources.end(); ++it)
00067 if (it->getSource() == source)
00068 {
00069 it->getMask() = eventMask;
00070 break;
00071 }
00072 }
00073
00074
00075
00076
00077 void
00078 XmlRpcDispatch::work(double timeout)
00079 {
00080
00081 _endTime = (timeout < 0.0) ? -1.0 : (getTime() + timeout);
00082 _doClear = false;
00083 _inWork = true;
00084
00085
00086 while (_sources.size() > 0) {
00087
00088
00089 fd_set inFd, outFd, excFd;
00090 FD_ZERO(&inFd);
00091 FD_ZERO(&outFd);
00092 FD_ZERO(&excFd);
00093
00094 int maxFd = -1;
00095 SourceList::iterator it;
00096 for (it=_sources.begin(); it!=_sources.end(); ++it) {
00097 int fd = it->getSource()->getfd();
00098 if (it->getMask() & ReadableEvent) FD_SET(fd, &inFd);
00099 if (it->getMask() & WritableEvent) FD_SET(fd, &outFd);
00100 if (it->getMask() & Exception) FD_SET(fd, &excFd);
00101 if (it->getMask() && fd > maxFd) maxFd = fd;
00102 }
00103
00104
00105 int nEvents;
00106 if (timeout < 0.0)
00107 nEvents = select(maxFd+1, &inFd, &outFd, &excFd, NULL);
00108 else
00109 {
00110 struct timeval tv;
00111 tv.tv_sec = (int)floor(timeout);
00112 tv.tv_usec = ((int)floor(1000000.0 * (timeout-floor(timeout)))) % 1000000;
00113 nEvents = select(maxFd+1, &inFd, &outFd, &excFd, &tv);
00114 }
00115
00116 if (nEvents < 0)
00117 {
00118 if(errno != EINTR)
00119 XmlRpcUtil::error("Error in XmlRpcDispatch::work: error in select (%d).", nEvents);
00120 _inWork = false;
00121 return;
00122 }
00123
00124
00125 for (it=_sources.begin(); it != _sources.end(); )
00126 {
00127 SourceList::iterator thisIt = it++;
00128 XmlRpcSource* src = thisIt->getSource();
00129 int fd = src->getfd();
00130 unsigned newMask = (unsigned) -1;
00131 if (fd <= maxFd) {
00132
00133 if (FD_ISSET(fd, &inFd))
00134 newMask &= src->handleEvent(ReadableEvent);
00135 if (FD_ISSET(fd, &outFd))
00136 newMask &= src->handleEvent(WritableEvent);
00137 if (FD_ISSET(fd, &excFd))
00138 newMask &= src->handleEvent(Exception);
00139
00140
00141
00142
00143 for (thisIt=_sources.begin(); thisIt != _sources.end(); thisIt++)
00144 {
00145 if(thisIt->getSource() == src)
00146 break;
00147 }
00148 if(thisIt == _sources.end())
00149 {
00150 XmlRpcUtil::error("Error in XmlRpcDispatch::work: couldn't find source iterator");
00151 continue;
00152 }
00153
00154 if ( ! newMask) {
00155 _sources.erase(thisIt);
00156 if ( ! src->getKeepOpen())
00157 src->close();
00158 } else if (newMask != (unsigned) -1) {
00159 thisIt->getMask() = newMask;
00160 }
00161 }
00162 }
00163
00164
00165 if (_doClear)
00166 {
00167 SourceList closeList = _sources;
00168 _sources.clear();
00169 for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) {
00170 XmlRpcSource *src = it->getSource();
00171 src->close();
00172 }
00173
00174 _doClear = false;
00175 }
00176
00177
00178 if (0 <= _endTime && getTime() > _endTime)
00179 break;
00180 }
00181
00182 _inWork = false;
00183 }
00184
00185
00186
00187
00188 void
00189 XmlRpcDispatch::exit()
00190 {
00191 _endTime = 0.0;
00192 }
00193
00194
00195 void
00196 XmlRpcDispatch::clear()
00197 {
00198 if (_inWork)
00199 _doClear = true;
00200 else
00201 {
00202 SourceList closeList = _sources;
00203 _sources.clear();
00204 for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it)
00205 it->getSource()->close();
00206 }
00207 }
00208
00209
00210 double
00211 XmlRpcDispatch::getTime()
00212 {
00213 #ifdef USE_FTIME
00214 struct timeb tbuff;
00215
00216 ftime(&tbuff);
00217 return ((double) tbuff.time + ((double)tbuff.millitm / 1000.0) +
00218 ((double) tbuff.timezone * 60));
00219 #else
00220 struct timeval tv;
00221 struct timezone tz;
00222
00223 gettimeofday(&tv, &tz);
00224 return (tv.tv_sec + tv.tv_usec / 1000000.0);
00225 #endif
00226 }
00227
00228