reSIProcate/rutil  9694
Poll.hxx
Go to the documentation of this file.
00001 #if !defined(RESIP_POLL_HXX)
00002 #define RESIP_POLL_HXX
00003 
00004 // One of the following macros must be defined:
00005 //#define RESIP_POLL_IMPL_POLL
00006 #define RESIP_POLL_IMPL_SELECT
00007 //#define RESIP_POLL_IMPL_EPOLL  // Not yet implemented.
00008 
00009 /*
00010   Define this macro to support applications that must call system call "poll"
00011   or its ilk themselves rather than calling method "Poll::wait".
00012 */
00013 #define RESIP_POLL_EXTERN
00014 
00015 #include <vector>
00016 
00017 #ifdef RESIP_POLL_IMPL_POLL
00018 #  include <sys/poll.h>
00019 #endif
00020 
00021 #ifdef RESIP_POLL_IMPL_SELECT
00022 # ifdef WIN32
00023 #  include <winsock2.h>
00024 # else
00025 #  include <sys/time.h>
00026 #  include <sys/types.h>
00027 #  include <unistd.h>
00028 # endif // WIN32
00029 #endif // RESIP_POLL_IMPL_SELECT
00030 
00031 #ifdef RESIP_POLL_EXTERN
00032 # include <map>
00033 #endif // RESI
00034 
00035 namespace resip {
00036 
00038 
00051 class Poll {
00052 
00053    public:
00054 
00055       class FDEntry {
00056 
00057             friend class Poll;
00058 
00059          public:
00060 
00061             typedef unsigned short StateBitMask; // FDStateBitMask | ResipStateBitMask.
00062             enum FDStateBitMaskEnum {
00063                fdsbmReadable       = 0x0001, // (POLLIN)
00064                fdsbmWritable       = 0x0004, // (POLLOUT)
00065                fdsbmError          = 0x0008, // (POLLERR)
00066                fdsbmAll            = Poll::FDEntry::fdsbmReadable |
00067                Poll::FDEntry::fdsbmWritable |
00068                Poll::FDEntry::fdsbmError
00069             };
00070             typedef StateBitMask FDStateBitMask;
00071             enum ResipStateBitMaskEnum {
00072                rsbmIsTransport    = 0x0040,
00073                rsbmIsWritePending = 0x0080
00074             };
00075             typedef StateBitMask ResipStateBitMask;
00076 
00077          private:
00078 
00079             static
00080             int
00081             compare(const Poll::FDEntry * leftFDEntry,
00082                     const Poll::FDEntry * rightFDEntry);
00083 
00084             // Fields:
00085             Poll *                       _poll;
00086             int/*FD*/                    _fd;
00087             Poll::FDEntry::StateBitMask  _stateBitMask;
00088             unsigned short               _index; // Within "_poll->_fdEntryVector".
00089 
00090          public:
00091 
00092             //constructor
00093             FDEntry(Poll *     poll,
00094                     bool       isTransport,
00095                     int/*FD*/  fd);
00096 
00097             //destructor
00098             virtual ~FDEntry();
00099 
00100             inline
00101             int//FD
00102             getFD() const
00103             {
00104                return _fd;
00105             }
00106 
00107             inline
00108             Poll::FDEntry::StateBitMask
00109             getStateBitMask() const
00110             {
00111                return _stateBitMask;
00112             }
00113 
00114             void
00115             clearFDState();
00116             
00117          protected:
00118 
00119             void
00120             setIsWritePending(bool isWritePending);
00121             
00122             virtual void doRead() {};
00123             virtual void doWrite() {};
00124             virtual void doError() {};
00125             
00126          private:
00127 
00128             // Copy constructor: declared but not defined
00129             FDEntry(const Poll::FDEntry &  from);
00130 
00131             // Assignment: declared but not defined
00132             Poll::FDEntry &
00133             operator=(const Poll::FDEntry &  from);
00134 
00135       };
00136       friend class Poll::FDEntry;
00137 
00138    private:
00139 
00140       // Fields:
00141       std::vector<Poll::FDEntry *>          _fdEntryVector;
00142 #ifdef RESIP_POLL_IMPL_POLL
00143       std::vector<pollfd>                   _pollFDVector;
00144 #endif
00145 #ifdef RESIP_POLL_IMPL_SELECT
00146       int/*FD*/                        _maxFDPlus1;
00147       fd_set                           _readFDSet;
00148       fd_set                           _writeFDSet;
00149 #endif
00150 #ifdef RESIP_POLL_EXTERN
00151       std::map<int/*FD*/, Poll::FDEntry *>  _fdEntryMap;
00152 #endif
00153       std::vector<Poll::FDEntry *>          _waitResult;
00154 
00155    public:
00156 
00157       /*
00158         "waitResult" is the result of method "wait" or "afterExternWait".
00159         Returns the index of the entry with the smallest file descriptor >= "fd" in
00160         "waitResult", or "waitResult.size()" if none exists.
00161       */
00162       static
00163       int
00164       findFDInWaitResult(int/*FD*/                        fd,
00165                          const std::vector<Poll::FDEntry *> &  waitResult);
00166 
00167       //constructor
00168       Poll();
00169 
00170       //destructor
00171       ~Poll();
00172 
00173 #ifdef RESIP_POLL_EXTERN  // {
00174 
00175       // The result is the set of entries in this poll object.
00176       const std::vector<Poll::FDEntry *> &
00177       beforeExternWait();
00178 
00179       /*
00180         If "fd" has no entry in this poll object, ignore it and return false.
00181         Otherwise, set the entry's FD state from "fdStateBitMask" and return true.
00182         If the same "fd" is passed in multiple times, the "fdStateBitMask" are
00183         or-ed together.
00184       */
00185       bool
00186       setEntryFDStateForExternWait(int/*FD*/                    fd,
00187                                    Poll::FDEntry::StateBitMask  fdStateBitMask);
00188 
00189       // The result is identical to that of method "wait".
00190       const std::vector<Poll::FDEntry *> &
00191       afterExternWait();
00192 
00193 #else //!defined(RESIP_POLL_EXTERN)  } {
00194 
00195       /*
00196         Wait for I/O on any of this poll object's entry's file descriptors.
00197         More precisely, wait for the file descriptor of any entry with a pending
00198         write to be writable or for any entry's file descriptor to have readable
00199         input or an error.
00200         If "timeoutMilliSeconds" is negative, it means wait indefinitely, otherwise
00201         it indicates the maximum period to wait.
00202         The result is an array of the entries for the file descriptors that are
00203         readable, writable, or error, as specified by each entry's FD state.
00204         The result contains no duplicates and is sorted by file descriptor.
00205         (To service file descriptors with round-robin prioritization, remember the
00206         last file descriptor serviced and use method "Poll::findFDInWaitResult" to
00207         find the index in the result array of the highest priority entry.)
00208         The result is valid until the next call to this method, method
00209         "beforeExternWait", or the destructor.
00210         At some point before then, for each entry in the result, method
00211         "Poll::FDEntry::clearFDState" must be called.
00212       */
00213       const std::vector<Poll::FDEntry *> &
00214       wait(int timeoutMilliSeconds);
00215 
00216 #endif //!defined(RESIP_POLL_EXTERN)  }
00217 
00218    private:
00219 
00220       // Copy constructor: declared but not defined
00221       Poll(const Poll &  from);
00222 
00223       // Assignment: declared but not defined
00224       Poll &
00225       operator=(const Poll &  from);
00226 
00227 };
00228 
00230 
00231 } // namespace resip
00232 
00233 #endif //!defined(RESIP_POLL_HXX)
00234 
00235 /* ====================================================================
00236  * The Vovida Software License, Version 1.0 
00237  * 
00238  * Copyright (c) 2000-2005 Jacob Butcher
00239  * 
00240  * Redistribution and use in source and binary forms, with or without
00241  * modification, are permitted provided that the following conditions
00242  * are met:
00243  * 
00244  * 1. Redistributions of source code must retain the above copyright
00245  *    notice, this list of conditions and the following disclaimer.
00246  * 
00247  * 2. Redistributions in binary form must reproduce the above copyright
00248  *    notice, this list of conditions and the following disclaimer in
00249  *    the documentation and/or other materials provided with the
00250  *    distribution.
00251  * 
00252  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00253  *    and "Vovida Open Communication Application Library (VOCAL)" must
00254  *    not be used to endorse or promote products derived from this
00255  *    software without prior written permission. For written
00256  *    permission, please contact vocal@vovida.org.
00257  *
00258  * 4. Products derived from this software may not be called "VOCAL", nor
00259  *    may "VOCAL" appear in their name, without prior written
00260  *    permission of Vovida Networks, Inc.
00261  * 
00262  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00263  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00264  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00265  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00266  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00267  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00268  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00269  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00270  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00271  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00272  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00273  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00274  * DAMAGE.
00275  * 
00276  */