< Previous by Date Date Index Next by Date >
< Previous in Thread Thread Index  

Re: [reSIProcate] RE: [Resiprocate-devel] proposed poll interface, with implementation


Any ideas on how many TCP connections can be supported using this?


On 8/6/04 1:25 PM, "Jason Fischl" <jason@xxxxxxxxxxxxxx> wrote:

> Hi Jacob,  (reposted to correct mailing list)
> 
> This interface looks excellent. I've had a look at it and it looks like the
> changes to the stack should be fairly minimal.
> 
> How do I add file descriptors to the fdEntryVector? There doesn't seem to be
> an interface to do this. What does the isTransport parameter on
> Poll::FDEntry constructor mean? How do I specify which StateBitMasks I want
> to wait on when I construct a FDEntry?
> 
> I see how to use the RESIP_POLL_EXTERN methods to add file descriptors but
> it doesn't seem like this interface is necessary unless the application is
> also going to add in its own filedescriptors. Do you think that each
> Transport object should have its own Poll object?
> 
> In your implementation of RESIP_POLL_IMPL_POLL do you copy the
> _fdEntryVector into an array before each call to poll? How do you deal with
> error conditions? Exceptions?
> 
> I'd like to take a crack at integrating your select and poll based
> implementations into resiprocate. This should greatly simplify the
> round-robin code in the TcpTransport and also greatly increase the number of
> open tcp connections that we can support. With the select implementation, it
> can continue to work on windows platforms as well.
> 
> Thanks,
> Jason
> 
> 
> 
>> -----Original Message-----
>> From: resiprocate-devel-admin@xxxxxxxxxxxxxxxxxxxxx
>> [mailto:resiprocate-devel-admin@xxxxxxxxxxxxxxxxxxxxx]On Behalf Of Jacob
>> Butcher
>> Sent: Friday, November 07, 2003 8:29 PM
>> To: resiprocate-devel@xxxxxxxxxxxxxxxxxxxxx
>> Subject: [Resiprocate-devel] proposed poll interface, with
>> implementation
>> 
>> 
>> I hear that abstracting the select call to be efficient, fair, portable,
>> and single-thread-friendly is a Good Thing.  So I wrote a class
>> to wrap it,
>> enclosed.  The basic idea is an interface that:
>> - is implementable in terms of select, poll, or epoll
>> - produces a sorted file descriptor sequence for easy round-robin ordering
>> - has very little overhead
>> - supports single-threaded applications.
>> The basic method and best place to start reading is "wait", 210
>> lines below.
>> 
>> I also wrote select and poll based implementations, not enclosed.
>> 
>>                                 Jacob Butcher
>> 
>> ################
>> # Poll.hxx
>> ################################################################
>> #ifndef RESIP_POLL_HXX
>> #define RESIP_POLL_HXX
>> 
>> // One of the following macros must be defined:
>> //#define RESIP_POLL_IMPL_POLL
>> #define RESIP_POLL_IMPL_SELECT
>> //#define RESIP_POLL_IMPL_EPOLL  // Not yet implemented.
>> 
>> /*
>> Define this macro to support applications that must call system
>> call "poll"
>> or its ilk themselves rather than calling method "Poll::wait".
>> */
>> #define RESIP_POLL_EXTERN
>> 
>> #include <vector>
>> #ifdef RESIP_POLL_IMPL_POLL
>> #include <sys/poll.h>
>> #endif
>> #ifdef RESIP_POLL_IMPL_SELECT
>> #include <sys/time.h>
>> #include <sys/types.h>
>> #include <unistd.h>
>> #endif
>> #ifdef RESIP_POLL_EXTERN
>> #include <map>
>> #endif
>> 
>> namespace resip {
>> 
>> //////////////////////////////////////////////////////////////////
>> /////////////
>> 
>> /*
>> This class abstracts the Unix system call "poll".
>> It offers implementations in terms of "poll" itself, "epoll", and
>> "select".
>> (Respectively #ifdef'd by RESIP_POLL_IMPL_POLL,
>> RESIP_POLL_IMPL_SELECT, and
>> RESIP_POLL_IMPL_EPOLL.)
>> File descriptors are wrapped by inner class "Poll::FDEntry".
>> The actual "poll" call is represented by method "wait", or if an
>> application
>> wants to control the system call directly, it can instead use methods
>> "beforeExternWait", "setEntryFDStateForExternWait", and "afterExternWait".
>> (The latter are selected by #define-ing RESIP_POLL_EXTERN.)
>> */
>> class Poll {
>> 
>>  public:
>> 
>>   class FDEntry {
>> 
>>     friend class Poll;
>> 
>>    public:
>> 
>>     typedef unsigned short StateBitMask; // FDStateBitMask |
>> ResipStateBitMask.
>>     enum FDStateBitMaskEnum {
>>       fdsbmReadable       = 0x0001, // (POLLIN)
>>       fdsbmWritable       = 0x0004, // (POLLOUT)
>>       fdsbmError          = 0x0008, // (POLLERR)
>>       fdsbmAll            = Poll::FDEntry::fdsbmReadable |
>>                             Poll::FDEntry::fdsbmWritable |
>>                             Poll::FDEntry::fdsbmError
>>     };
>>     typedef StateBitMask FDStateBitMask;
>>     enum ResipStateBitMaskEnum {
>>       rsbmIsTransport    = 0x0040,
>>       rsbmIsWritePending = 0x0080
>>     };
>>     typedef StateBitMask ResipStateBitMask;
>> 
>>    private:
>> 
>>     static
>>     int
>>     compare(const Poll::FDEntry * leftFDEntry,
>>             const Poll::FDEntry * rightFDEntry);
>> 
>>     // Fields:
>>     Poll *                       _poll;
>>     int/*FD*/                    _fd;
>>     Poll::FDEntry::StateBitMask  _stateBitMask;
>>     unsigned short               _index; // Within
>> "_poll->_fdEntryVector".
>> 
>>    public:
>> 
>>     //constructor
>>     FDEntry(Poll *     poll,
>>             bool       isTransport,
>>             int/*FD*/  fd);
>> 
>>     //destructor
>>     ~FDEntry();
>> 
>>     inline
>>     int//FD
>>     getFD() const
>>     {
>>       return _fd;
>>     }
>> 
>>     inline
>>     Poll::FDEntry::StateBitMask
>>     getStateBitMask() const
>>     {
>>       return _stateBitMask;
>>     }
>> 
>>     void
>>     clearFDState();
>> 
>>    protected:
>> 
>>     void
>>     setIsWritePending(bool isWritePending);
>> 
>>    private:
>> 
>>     // Copy constructor: declared but not defined
>>     FDEntry(const Poll::FDEntry &  from);
>> 
>>     // Assignment: declared but not defined
>>     Poll::FDEntry &
>>     operator=(const Poll::FDEntry &  from);
>> 
>>   };
>>   friend class Poll::FDEntry;
>> 
>>  private:
>> 
>>   // Fields:
>>   vector<Poll::FDEntry *>          _fdEntryVector;
>> #ifdef RESIP_POLL_IMPL_POLL
>>   vector<pollfd>                   _pollFDVector;
>> #endif
>> #ifdef RESIP_POLL_IMPL_SELECT
>>   int/*FD*/                        _maxFDPlus1;
>>   fd_set                           _readFDSet;
>>   fd_set                           _writeFDSet;
>> #endif
>> #ifdef RESIP_POLL_EXTERN
>>   map<int/*FD*/, Poll::FDEntry *>  _fdEntryMap;
>> #endif
>>   vector<Poll::FDEntry *>          _waitResult;
>> 
>>  public:
>> 
>>   /*
>>   "waitResult" is the result of method "wait" or "afterExternWait".
>>   Returns the index of the entry with the smallest file
>> descriptor >= "fd" in
>>   "waitResult", or "waitResult.size()" if none exists.
>>   */
>>   static
>>   int
>>   findFDInWaitResult(int/*FD*/                        fd,
>>                      const vector<Poll::FDEntry *> &  waitResult);
>> 
>>   //constructor
>>   Poll();
>> 
>>   //destructor
>>   ~Poll();
>> 
>> #ifdef RESIP_POLL_EXTERN  // {
>> 
>>   // The result is the set of entries in this poll object.
>>   const vector<Poll::FDEntry *> &
>>   beforeExternWait();
>> 
>>   /*
>>   If "fd" has no entry in this poll object, ignore it and return false.
>>   Otherwise, set the entry's FD state from "fdStateBitMask" and
>> return true.
>>   If the same "fd" is passed in multiple times, the "fdStateBitMask" are
>>   or-ed together.
>>   */
>>   bool
>>   setEntryFDStateForExternWait(int/*FD*/                    fd,
>>                                Poll::FDEntry::StateBitMask
>> fdStateBitMask);
>> 
>>   // The result is identical to that of method "wait".
>>   const vector<Poll::FDEntry *> &
>>   afterExternWait();
>> 
>> #else //!defined(RESIP_POLL_EXTERN)  } {
>> 
>>   /*
>>   Wait for I/O on any of this poll object's entry's file descriptors.
>>   More precisely, wait for the file descriptor of any entry with a pending
>>   write to be writable or for any entry's file descriptor to have readable
>>   input or an error.
>>   If "timeoutMilliSeconds" is negative, it means wait
>> indefinitely, otherwise
>>   it indicates the maximum period to wait.
>>   The result is an array of the entries for the file descriptors that are
>>   readable, writable, or error, as specified by each entry's FD state.
>>   The result contains no duplicates and is sorted by file descriptor.
>>   (To service file descriptors with round-robin prioritization,
>> remember the
>>   last file descriptor serviced and use method
>> "Poll::findFDInWaitResult" to
>>   find the index in the result array of the highest priority entry.)
>>   The result is valid until the next call to this method, method
>>   "beforeExternWait", or the destructor.
>>   At some point before then, for each entry in the result, method
>>   "Poll::FDEntry::clearFDState" must be called.
>>   */
>>   const vector<Poll::FDEntry *> &
>>   wait(int timeoutMilliSeconds);
>> 
>> #endif //!defined(RESIP_POLL_EXTERN)  }
>> 
>>  private:
>> 
>>   // Copy constructor: declared but not defined
>>   Poll(const Poll &  from);
>> 
>>   // Assignment: declared but not defined
>>   Poll &
>>   operator=(const Poll &  from);
>> 
>> };
>> 
>> //////////////////////////////////////////////////////////////////
>> /////////////
>> 
>> } // namespace resip
>> 
>> #endif //!defined(RESIP_POLL_HXX)
>> ################################################################
>> 
>> 
>> -------------------------------------------------------
>> This SF.Net email sponsored by: ApacheCon 2003,
>> 16-19 November in Las Vegas. Learn firsthand the latest
>> developments in Apache, PHP, Perl, XML, Java, MySQL,
>> WebDAV, and more! http://www.apachecon.com/
>> _______________________________________________
>> Resiprocate-devel mailing list
>> Resiprocate-devel@xxxxxxxxxxxxxxxxxxxxx
>> https://lists.sourceforge.net/lists/listinfo/resiprocate-devel
>> 
> 
> 
> _______________________________________________
> resiprocate-devel mailing list
> resiprocate-devel@xxxxxxxxxxxxxxxxxxx
> https://list.sipfoundry.org/mailman/listinfo/resiprocate-devel