reSIProcate/rutil  9694
Poll.cxx
Go to the documentation of this file.
00001 #include <stdlib.h>
00002 #include "rutil/Poll.hxx"
00003 
00004 using namespace resip;
00005 using namespace std;
00006 
00007 #if !defined(RESIP_POLL_IMPL_POLL) && !defined(RESIP_POLL_IMPL_SELECT) && !defined(RESIP_POLL_EPOLL)
00008 #error "Define one of RESIP_POLL_IMPL_POLL, RESIP_POLL_IMPL_SELECT, or RESIP_POLL_EPOLL."
00009 #endif
00010 
00012 
00013 //constructor
00014 Poll::FDEntry::FDEntry(Poll* poll,
00015                        bool isTransport,
00016                        int/*FD*/  fd) :
00017    _poll(poll),
00018    _fd(fd),
00019    _stateBitMask(isTransport ? Poll::FDEntry::rsbmIsTransport : 0),
00020    _index((unsigned short)poll->_fdEntryVector.size())
00021 {
00022    _poll->_fdEntryVector.push_back(this);
00023 #ifdef RESIP_POLL_IMPL_POLL
00024    pollfd pollFD;
00025    pollFD.fd = fd;
00026    pollFD.events = POLLIN;
00027    _poll->_pollFDVector.push_back(pollFD);
00028 #endif
00029 #ifdef RESIP_POLL_IMPL_SELECT
00030    if (_fd >= _poll->_maxFDPlus1) 
00031    {
00032       _poll->_maxFDPlus1 = _fd + 1;
00033    }
00034    FD_SET(_fd, &(_poll->_readFDSet));
00035 #endif
00036 #ifdef RESIP_POLL_EXTERN
00037    _poll->_fdEntryMap.insert(std::pair<int/*FD*/, Poll::FDEntry *>(_fd, this));
00038 #endif
00039 }
00040 
00041 //destructor
00042 Poll::FDEntry::~FDEntry()
00043 {
00044    vector<Poll::FDEntry *> &fdEntryVector = _poll->_fdEntryVector;
00045    Poll::FDEntry *lastFDEntry = fdEntryVector[fdEntryVector.size() - 1];
00046    lastFDEntry->_index = _index;
00047    fdEntryVector[_index] = lastFDEntry;
00048    fdEntryVector.pop_back();
00049 #ifdef RESIP_POLL_IMPL_POLL
00050    vector<pollfd> &pollFDVector = _poll->_pollFDVector;
00051    pollFDVector[_index] = pollFDVector[pollFDVector.size() - 1];
00052    pollFDVector.pop_back();
00053 #endif
00054 #ifdef RESIP_POLL_IMPL_SELECT
00055    FD_CLR(_fd, &(_poll->_readFDSet));
00056    FD_CLR(_fd, &(_poll->_writeFDSet));
00057 #endif
00058 #ifdef RESIP_POLL_EXTERN
00059    _poll->_fdEntryMap.erase(_fd);
00060 #endif
00061 }
00062 
00063 void
00064 Poll::FDEntry::clearFDState()
00065 {
00066    _stateBitMask &= ~Poll::FDEntry::fdsbmAll;
00067 }
00068 
00069 void
00070 Poll::FDEntry::setIsWritePending(bool isWritePending)
00071 {
00072    if (isWritePending) 
00073    {
00074       _stateBitMask |= Poll::FDEntry::rsbmIsWritePending;
00075 #ifdef RESIP_POLL_IMPL_POLL
00076       _poll->_pollFDVector[_index].events |= Poll::FDEntry::fdsbmWritable;
00077 #endif
00078 #ifdef RESIP_POLL_IMPL_SELECT
00079       FD_SET(_fd, &(_poll->_writeFDSet));
00080 #endif
00081    } else 
00082    {
00083       _stateBitMask &= ~Poll::FDEntry::rsbmIsWritePending;
00084 #ifdef RESIP_POLL_IMPL_POLL
00085       _poll->_pollFDVector[_index].events &= ~Poll::FDEntry::fdsbmWritable;
00086 #endif
00087 #ifdef RESIP_POLL_IMPL_SELECT
00088       FD_CLR(_fd, &(_poll->_writeFDSet));
00089 #endif
00090    }
00091 }
00092 
00093 //static
00094 int
00095 Poll::FDEntry::compare(const Poll::FDEntry * leftFDEntry,
00096                        const Poll::FDEntry * rightFDEntry)
00097 {
00098    return (leftFDEntry->getFD() - rightFDEntry->getFD());
00099 }
00100 
00102 
00103 //static
00104 int
00105 Poll::findFDInWaitResult(int/*FD*/                        fd,
00106                          const vector<Poll::FDEntry *> &  waitResult)
00107 {
00108    unsigned int lowIndex = 0;
00109    unsigned int highIndex = (unsigned int)waitResult.size();
00110    while (lowIndex + 1 < highIndex) 
00111    {
00112       // The goal fd is in waitResult in the range [lowIndex, highIndex[.
00113       unsigned int midIndex = (lowIndex + highIndex) / 2;
00114       if (waitResult[midIndex]->_fd > fd) 
00115       {
00116          highIndex = midIndex - 1;
00117       } 
00118       else 
00119       {
00120          lowIndex = midIndex;
00121       }
00122    }//while
00123    return lowIndex;
00124 }
00125 
00126 //constructor
00127 Poll::Poll()
00128 #ifdef RESIP_POLL_IMPL_SELECT
00129    :
00130 _maxFDPlus1(0) 
00131 #endif
00132 {
00133 #ifdef RESIP_POLL_IMPL_SELECT
00134    FD_ZERO(&_readFDSet);
00135    FD_ZERO(&_writeFDSet);
00136 #endif
00137 }
00138 
00139 //destructor
00140 Poll::~Poll()
00141 {
00142 }
00143 
00144 #ifdef RESIP_POLL_EXTERN  // {
00145 
00146 const vector<Poll::FDEntry *> &
00147 Poll::beforeExternWait()
00148 {
00149    _waitResult.clear();
00150    return _fdEntryVector;
00151 }
00152 
00153 bool
00154 Poll::setEntryFDStateForExternWait(int/*FD*/                    fd,
00155                                    Poll::FDEntry::StateBitMask  fdStateBitMask)
00156 {
00157    map<int/*FD*/, Poll::FDEntry *>::const_iterator fdEntryIterator =
00158       _fdEntryMap.find(fd);
00159    bool isFDInPoll = (fdEntryIterator != _fdEntryMap.end());
00160    if (isFDInPoll) 
00161    {
00162       Poll::FDEntry *fdEntry = fdEntryIterator->second;
00163       fdEntry->_stateBitMask |= fdStateBitMask & Poll::FDEntry::fdsbmAll;
00164       _waitResult.push_back(fdEntry);
00165    }
00166    return isFDInPoll;
00167 }
00168 
00169 const vector<Poll::FDEntry *> &
00170 Poll::afterExternWait()
00171 {
00172    return _waitResult;
00173 }
00174 
00175 #else //!defined(RESIP_POLL_EXTERN)  } {
00176 
00177 const vector<Poll::FDEntry *> &
00178 Poll::wait(int timeoutMilliSeconds)
00179 {
00180    _waitResult.clear();
00181 #ifdef RESIP_POLL_IMPL_POLL
00182    pollfd *pollFDArray = &(_pollFDVector.front());
00183    int numReadyFDs = poll(pollFDArray,
00184                           _pollFDVector.size(),
00185                           timeoutMilliSeconds);
00186    if (numReadyFDs < 0) 
00187    {
00189    }
00190    for (unsigned short index = 0; numReadyFDs > 0; ++index) 
00191    {
00192       int revents = pollFDArray[index].revents;
00193       if (revents) 
00194       {
00195          Poll::FDEntry *fdEntry = _fdEntryVector[index];
00196          fdEntry->_stateBitMask |= revents;
00197          _waitResult.push_back(fdEntry);
00198          --numReadyFDs;
00199       }
00200    }//for
00201    qsort(&(_waitResult.front()),
00202          _waitResult.size(),
00203          sizeof(Poll::FDEntry *),
00204          reinterpret_cast<int(*)(const void *,
00205                                  const void *)>(&Poll::FDEntry::compare));
00206 #endif
00207 #ifdef RESIP_POLL_IMPL_SELECT
00208    fd_set readableFDSet = _readFDSet;
00209    fd_set writableFDSet = _writeFDSet;
00210    fd_set errorFDSet = _readFDSet;
00211    timeval timeoutTimeVal;
00212    timeoutTimeVal.tv_sec = timeoutMilliSeconds / 1000;
00213    timeoutTimeVal.tv_usec = 1000 * (timeoutMilliSeconds % 1000);
00214    int numReadyFDs = select(_maxFDPlus1,
00215                             &readableFDSet,
00216                             &writableFDSet,
00217                             &errorFDSet,
00218                             &timeoutTimeVal);
00219    if (numReadyFDs < 0) 
00220    {
00222    }
00223    for (unsigned short index = 0; numReadyFDs > 0; ++index) 
00224    {
00225       Poll::FDEntry *fdEntry = _fdEntryVector[index];
00226       bool isFDReadable = FD_ISSET(fdEntry->_fd, &readableFDSet);
00227       bool isFDWritable = FD_ISSET(fdEntry->_fd, &writableFDSet);
00228       bool isFDError = FD_ISSET(fdEntry->_fd, &errorFDSet);
00229       if (isFDReadable || isFDWritable || isFDError) 
00230       {
00231          if (isFDReadable) 
00232          {
00233             fdEntry->_stateBitMask |= Poll::FDEntry::fdsbmReadable;
00234          }
00235          if (isFDWritable) 
00236          {
00237             fdEntry->_stateBitMask |= Poll::FDEntry::fdsbmWritable;
00238          }
00239          if (isFDError) 
00240          {
00241             fdEntry->_stateBitMask |= Poll::FDEntry::fdsbmError;
00242          }
00243          _waitResult.push_back(fdEntry);
00244          --numReadyFDs;
00245       }
00246    }//for
00247 #endif
00248    return _waitResult;
00249 }
00250 
00251 #endif //!defined(RESIP_POLL_EXTERN)  }
00252 
00253 /* ====================================================================
00254  * The Vovida Software License, Version 1.0 
00255  * 
00256  * Copyright (c) 2000-2005 Jacob Butcher
00257  * 
00258  * Redistribution and use in source and binary forms, with or without
00259  * modification, are permitted provided that the following conditions
00260  * are met:
00261  * 
00262  * 1. Redistributions of source code must retain the above copyright
00263  *    notice, this list of conditions and the following disclaimer.
00264  * 
00265  * 2. Redistributions in binary form must reproduce the above copyright
00266  *    notice, this list of conditions and the following disclaimer in
00267  *    the documentation and/or other materials provided with the
00268  *    distribution.
00269  * 
00270  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00271  *    and "Vovida Open Communication Application Library (VOCAL)" must
00272  *    not be used to endorse or promote products derived from this
00273  *    software without prior written permission. For written
00274  *    permission, please contact vocal@vovida.org.
00275  *
00276  * 4. Products derived from this software may not be called "VOCAL", nor
00277  *    may "VOCAL" appear in their name, without prior written
00278  *    permission of Vovida Networks, Inc.
00279  * 
00280  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00281  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00282  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00283  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00284  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00285  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00286  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00287  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00288  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00289  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00290  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00291  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00292  * DAMAGE.
00293  *
00294  */