reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
Poll.cxx
Go to the documentation of this file.
1#include <stdlib.h>
2
3// One of the following macros must be defined:
4//#define RESIP_POLL_IMPL_POLL
5#define RESIP_POLL_IMPL_SELECT
6//#define RESIP_POLL_IMPL_EPOLL // Not yet implemented.
7
8/*
9 Define this macro to support applications that must call system call "poll"
10 or its ilk themselves rather than calling method "Poll::wait".
11*/
12#define RESIP_POLL_EXTERN
13
14#include "rutil/Poll.hxx"
15
16#include <vector>
17
18#ifdef RESIP_POLL_IMPL_POLL
19# include <sys/poll.h>
20#endif
21
22#ifdef RESIP_POLL_IMPL_SELECT
23# ifdef WIN32
24# include <winsock2.h>
25# else
26# include <sys/time.h>
27# include <sys/types.h>
28# include <unistd.h>
29# endif // WIN32
30#endif // RESIP_POLL_IMPL_SELECT
31
32#ifdef RESIP_POLL_EXTERN
33# include <map>
34#endif // RESIP_POLL_EXTERN
35
36using namespace resip;
37using namespace std;
38
39#if !defined(RESIP_POLL_IMPL_POLL) && !defined(RESIP_POLL_IMPL_SELECT) && !defined(RESIP_POLL_EPOLL)
40#error "Define one of RESIP_POLL_IMPL_POLL, RESIP_POLL_IMPL_SELECT, or RESIP_POLL_EPOLL."
41#endif
42
43namespace resip
44{
45// We hide anything that effects the ABI here
47{
48 public:
49 PollImpl();
50 ~PollImpl();
51 // Fields:
52 std::vector<Poll::FDEntry *> _fdEntryVector;
53#ifdef RESIP_POLL_IMPL_POLL
54 std::vector<pollfd> _pollFDVector;
55#endif
56#ifdef RESIP_POLL_IMPL_SELECT
57 int/*FD*/ _maxFDPlus1;
58 fd_set _readFDSet;
60#endif
61#ifdef RESIP_POLL_EXTERN
62 std::map<int/*FD*/, Poll::FDEntry *> _fdEntryMap;
63#endif
64 std::vector<Poll::FDEntry *> _waitResult;
65
66
67};
68}
69
71#ifdef RESIP_POLL_IMPL_SELECT
72 :
73_maxFDPlus1(0)
74#endif
75{
76#ifdef RESIP_POLL_IMPL_SELECT
77 FD_ZERO(&_readFDSet);
78 FD_ZERO(&_writeFDSet);
79#endif
80}
81
84
86
87//constructor
89 bool isTransport,
90 int/*FD*/ fd) :
91 _poll(poll),
92 _fd(fd),
93 _stateBitMask(isTransport ? Poll::FDEntry::rsbmIsTransport : 0),
94 _index((unsigned short)poll->mImpl->_fdEntryVector.size())
95{
96 _poll->mImpl->_fdEntryVector.push_back(this);
97#ifdef RESIP_POLL_IMPL_POLL
98 pollfd pollFD;
99 pollFD.fd = fd;
100 pollFD.events = POLLIN;
101 _poll->mImpl->_pollFDVector.push_back(pollFD);
102#endif
103#ifdef RESIP_POLL_IMPL_SELECT
104 if (_fd >= _poll->mImpl->_maxFDPlus1)
105 {
106 _poll->mImpl->_maxFDPlus1 = _fd + 1;
107 }
108 FD_SET(_fd, &(_poll->mImpl->_readFDSet));
109#endif
110#ifdef RESIP_POLL_EXTERN
111 _poll->mImpl->_fdEntryMap.insert(std::pair<int/*FD*/, Poll::FDEntry *>(_fd, this));
112#endif
113}
114
115//destructor
117{
118 vector<Poll::FDEntry *> &fdEntryVector = _poll->mImpl->_fdEntryVector;
119 Poll::FDEntry *lastFDEntry = fdEntryVector[fdEntryVector.size() - 1];
120 lastFDEntry->_index = _index;
121 fdEntryVector[_index] = lastFDEntry;
122 fdEntryVector.pop_back();
123#ifdef RESIP_POLL_IMPL_POLL
124 vector<pollfd> &pollFDVector = _poll->mImpl->_pollFDVector;
125 pollFDVector[_index] = pollFDVector[pollFDVector.size() - 1];
126 pollFDVector.pop_back();
127#endif
128#ifdef RESIP_POLL_IMPL_SELECT
129 FD_CLR(_fd, &(_poll->mImpl->_readFDSet));
130 FD_CLR(_fd, &(_poll->mImpl->_writeFDSet));
131#endif
132#ifdef RESIP_POLL_EXTERN
133 _poll->mImpl->_fdEntryMap.erase(_fd);
134#endif
135}
136
137void
142
143void
145{
146 if (isWritePending)
147 {
148 _stateBitMask |= Poll::FDEntry::rsbmIsWritePending;
149#ifdef RESIP_POLL_IMPL_POLL
150 _poll->mImpl->_pollFDVector[_index].events |= Poll::FDEntry::fdsbmWritable;
151#endif
152#ifdef RESIP_POLL_IMPL_SELECT
153 FD_SET(_fd, &(_poll->mImpl->_writeFDSet));
154#endif
155 } else
156 {
157 _stateBitMask &= ~Poll::FDEntry::rsbmIsWritePending;
158#ifdef RESIP_POLL_IMPL_POLL
159 _poll->mImpl->_pollFDVector[_index].events &= ~Poll::FDEntry::fdsbmWritable;
160#endif
161#ifdef RESIP_POLL_IMPL_SELECT
162 FD_CLR(_fd, &(_poll->mImpl->_writeFDSet));
163#endif
164 }
165}
166
167//static
168int
169Poll::FDEntry::compare(const Poll::FDEntry * leftFDEntry,
170 const Poll::FDEntry * rightFDEntry)
171{
172 return (leftFDEntry->getFD() - rightFDEntry->getFD());
173}
174
176
177//static
178int
180 const vector<Poll::FDEntry *> & waitResult)
181{
182 unsigned int lowIndex = 0;
183 unsigned int highIndex = (unsigned int)waitResult.size();
184 while (lowIndex + 1 < highIndex)
185 {
186 // The goal fd is in waitResult in the range [lowIndex, highIndex[.
187 unsigned int midIndex = (lowIndex + highIndex) / 2;
188 if (waitResult[midIndex]->_fd > fd)
189 {
190 highIndex = midIndex - 1;
191 }
192 else
193 {
194 lowIndex = midIndex;
195 }
196 }//while
197 return lowIndex;
198}
199
200//constructor
202 mImpl(new PollImpl)
203{}
204
205//destructor
207{
208}
209
210#ifdef RESIP_POLL_EXTERN // {
211
212const vector<Poll::FDEntry *> &
213Poll::beforeExternWait()
214{
215 mImpl->_waitResult.clear();
216 return mImpl->_fdEntryVector;
217}
218
219bool
220Poll::setEntryFDStateForExternWait(int/*FD*/ fd,
221 Poll::FDEntry::StateBitMask fdStateBitMask)
222{
223 map<int/*FD*/, Poll::FDEntry *>::const_iterator fdEntryIterator =
224 mImpl->_fdEntryMap.find(fd);
225 bool isFDInPoll = (fdEntryIterator != mImpl->_fdEntryMap.end());
226 if (isFDInPoll)
227 {
228 Poll::FDEntry *fdEntry = fdEntryIterator->second;
229 fdEntry->_stateBitMask |= fdStateBitMask & Poll::FDEntry::fdsbmAll;
230 mImpl->_waitResult.push_back(fdEntry);
231 }
232 return isFDInPoll;
233}
234
235const vector<Poll::FDEntry *> &
236Poll::afterExternWait()
237{
238 return mImpl->_waitResult;
239}
240
241#else
242
243const vector<Poll::FDEntry *> &
244Poll::wait(int timeoutMilliSeconds)
245{
246 mImpl->_waitResult.clear();
247#ifdef RESIP_POLL_IMPL_POLL
248 pollfd *pollFDArray = &(mImpl->_pollFDVector.front());
249 int numReadyFDs = poll(pollFDArray,
250 mImpl->_pollFDVector.size(),
251 timeoutMilliSeconds);
252 if (numReadyFDs < 0)
253 {
255 }
256 for (unsigned short index = 0; numReadyFDs > 0; ++index)
257 {
258 int revents = pollFDArray[index].revents;
259 if (revents)
260 {
261 Poll::FDEntry *fdEntry = mImpl->_fdEntryVector[index];
262 fdEntry->_stateBitMask |= revents;
263 mImpl->_waitResult.push_back(fdEntry);
264 --numReadyFDs;
265 }
266 }//for
267 qsort(&(mImpl->_waitResult.front()),
268 mImpl->_waitResult.size(),
269 sizeof(Poll::FDEntry *),
270 reinterpret_cast<int(*)(const void *,
271 const void *)>(&Poll::FDEntry::compare));
272#endif
273#ifdef RESIP_POLL_IMPL_SELECT
274 fd_set readableFDSet = mImpl->_readFDSet;
275 fd_set writableFDSet = mImpl->_writeFDSet;
276 fd_set errorFDSet = mImpl->_readFDSet;
277 timeval timeoutTimeVal;
278 timeoutTimeVal.tv_sec = timeoutMilliSeconds / 1000;
279 timeoutTimeVal.tv_usec = 1000 * (timeoutMilliSeconds % 1000);
280 int numReadyFDs = select(mImpl->_maxFDPlus1,
281 &readableFDSet,
282 &writableFDSet,
283 &errorFDSet,
284 &timeoutTimeVal);
285 if (numReadyFDs < 0)
286 {
288 }
289 for (unsigned short index = 0; numReadyFDs > 0; ++index)
290 {
291 Poll::FDEntry *fdEntry = mImpl->_fdEntryVector[index];
292 bool isFDReadable = FD_ISSET(fdEntry->_fd, &readableFDSet);
293 bool isFDWritable = FD_ISSET(fdEntry->_fd, &writableFDSet);
294 bool isFDError = FD_ISSET(fdEntry->_fd, &errorFDSet);
295 if (isFDReadable || isFDWritable || isFDError)
296 {
297 if (isFDReadable)
298 {
299 fdEntry->_stateBitMask |= Poll::FDEntry::fdsbmReadable;
300 }
301 if (isFDWritable)
302 {
303 fdEntry->_stateBitMask |= Poll::FDEntry::fdsbmWritable;
304 }
305 if (isFDError)
306 {
307 fdEntry->_stateBitMask |= Poll::FDEntry::fdsbmError;
308 }
309 mImpl->_waitResult.push_back(fdEntry);
310 --numReadyFDs;
311 }
312 }//for
313#endif
314 return mImpl->_waitResult;
315}
316
317#endif
318
319/* ====================================================================
320 * The Vovida Software License, Version 1.0
321 *
322 * Copyright (c) 2000-2005 Jacob Butcher
323 *
324 * Redistribution and use in source and binary forms, with or without
325 * modification, are permitted provided that the following conditions
326 * are met:
327 *
328 * 1. Redistributions of source code must retain the above copyright
329 * notice, this list of conditions and the following disclaimer.
330 *
331 * 2. Redistributions in binary form must reproduce the above copyright
332 * notice, this list of conditions and the following disclaimer in
333 * the documentation and/or other materials provided with the
334 * distribution.
335 *
336 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
337 * and "Vovida Open Communication Application Library (VOCAL)" must
338 * not be used to endorse or promote products derived from this
339 * software without prior written permission. For written
340 * permission, please contact vocal@vovida.org.
341 *
342 * 4. Products derived from this software may not be called "VOCAL", nor
343 * may "VOCAL" appear in their name, without prior written
344 * permission of Vovida Networks, Inc.
345 *
346 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
347 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
348 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
349 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
350 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
351 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
352 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
353 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
354 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
355 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
356 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
357 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
358 * DAMAGE.
359 *
360 */
fd_set _readFDSet
Definition Poll.cxx:58
int _maxFDPlus1
Definition Poll.cxx:57
std::vector< Poll::FDEntry * > _fdEntryVector
Definition Poll.cxx:52
std::map< int, Poll::FDEntry * > _fdEntryMap
Definition Poll.cxx:62
fd_set _writeFDSet
Definition Poll.cxx:59
std::vector< Poll::FDEntry * > _waitResult
Definition Poll.cxx:64
FDEntry(Poll *poll, bool isTransport, int fd)
Definition Poll.cxx:88
int getFD() const
Definition Poll.hxx:76
unsigned short StateBitMask
Definition Poll.hxx:35
virtual ~FDEntry()
Definition Poll.cxx:116
void setIsWritePending(bool isWritePending)
Definition Poll.cxx:144
This class abstracts the Unix system call "poll".
Definition Poll.hxx:25
const std::vector< Poll::FDEntry * > & wait(int timeoutMilliSeconds)
defined(RESIP_POLL_EXTERN) } {
static int findFDInWaitResult(int fd, const std::vector< Poll::FDEntry * > &waitResult)
Definition Poll.cxx:179
dcm! – add UnusedChecking(_enum) below;