39#include "blocxx/BLOCXX_config.h"
47#if defined(BLOCXX_WIN32)
55 #ifdef BLOCXX_HAVE_SYS_EPOLL_H
56 #include <sys/epoll.h>
58 #if defined (BLOCXX_HAVE_SYS_POLL_H)
61 #if defined (BLOCXX_HAVE_SYS_SELECT_H)
62 #include <sys/select.h>
66#ifdef BLOCXX_HAVE_SYS_TIME_H
72#ifdef BLOCXX_HAVE_UNISTD_H
87 const float LOOP_TIMEOUT = 10.0;
97#if defined(BLOCXX_WIN32)
103 size_t hcount =
static_cast<DWORD
>(selarray.size());
106 size_t handleidx = 0;
107 for (
size_t i = 0; i < selarray.size(); i++, handleidx++)
109 if(selarray[i].s.isSocket && selarray[i].s.networkevents)
111 ::WSAEventSelect(selarray[i].s.sockfd,
112 selarray[i].s.event, selarray[i].s.networkevents);
115 hdls[handleidx] = selarray[i].s.event;
118 TimeoutTimer timer(timeout);
120 DWORD cc = ::WaitForMultipleObjects(hcount, hdls.get(), FALSE, timer.asDWORDMs());
122 assert(cc != WAIT_ABANDONED);
133 rc = cc - WAIT_OBJECT_0;
137 if(selarray[rc].s.isSocket)
139 if(selarray[rc].s.networkevents
140 && selarray[rc].s.doreset ==
false)
142 ::WSAEventSelect(selarray[rc].s.sockfd,
143 selarray[rc].s.event, selarray[rc].s.networkevents);
148 ::WSAEventSelect(selarray[rc].s.sockfd,
149 selarray[rc].s.event, 0);
151 ::ioctlsocket(selarray[rc].s.sockfd, FIONBIO, &ioctlarg);
160 int availableCount = 0;
161 for (
size_t i = 0; i < selarray.size(); i++)
163 if( WaitForSingleObject(selarray[i].s.event, 0) == WAIT_OBJECT_0 )
165 if( selarray[i].waitForRead )
166 selarray[i].readAvailable =
true;
167 if( selarray[i].waitForWrite )
168 selarray[i].writeAvailable =
true;
173 selarray[i].readAvailable =
false;
174 selarray[i].writeAvailable =
false;
177 return availableCount;
188#ifdef BLOCXX_HAVE_SYS_EPOLL_H
202 UInt32
const read_events = EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP;
203 UInt32
const write_events = EPOLLOUT | EPOLLERR | EPOLLHUP;
204 for (
size_t i = 0; i < selarray.
size(); i++)
207 selarray[i].readAvailable =
false;
208 selarray[i].writeAvailable =
false;
209 selarray[i].wasError =
false;
210 events[i].data = epoll_data_t();
211 events[i].data.u32 = i;
212 events[i].events = 0;
213 if(selarray[i].waitForRead)
215 events[i].events |= read_events;
217 if(selarray[i].waitForWrite)
219 events[i].events |= write_events;
222 if(epoll_ctl(epfd.
get(), EPOLL_CTL_ADD, selarray[i].s, &events[i]) != 0)
236 const float maxWaitSec = LOOP_TIMEOUT;
237 ecc = epoll_wait(epfd.
get(), events.
get(), selarray.
size(), timer.
asIntMs(maxWaitSec));
239 if (ecc < 0 && errno == EINTR)
246 }
while ((ecc == 0) && !timer.
expired());
258 for(
int i = 0; i < ecc; i++)
276#if defined (BLOCXX_HAVE_SYS_POLL_H)
288 for (
size_t i = 0; i < selarray.
size(); i++)
291 selarray[i].readAvailable =
false;
292 selarray[i].writeAvailable =
false;
293 selarray[i].wasError =
false;
295 pfds[i].fd = selarray[i].s;
296 pfds[i].events = selarray[i].waitForRead ? (POLLIN | POLLPRI) : 0;
297 if(selarray[i].waitForWrite)
298 pfds[i].events |= POLLOUT;
302 const float maxWaitSec = LOOP_TIMEOUT;
303 rc = ::poll(pfds.
get(), selarray.
size(), timer.
asIntMs(maxWaitSec));
305 if (rc < 0 && errno == EINTR)
320 }
while ((rc == 0) && !timer.
expired());
331 for (
size_t i = 0; i < selarray.
size(); i++)
333 if (pfds[i].revents & (POLLERR | POLLNVAL))
335 selarray[i].wasError =
true;
338 if(selarray[i].waitForRead)
340 selarray[i].readAvailable = (pfds[i].revents &
341 (POLLIN | POLLPRI | POLLHUP));
344 if(selarray[i].waitForWrite)
346 selarray[i].writeAvailable = (pfds[i].revents &
347 (POLLOUT | POLLHUP));
361#if defined (BLOCXX_HAVE_SYS_SELECT_H)
376 for (
size_t i = 0; i < selarray.
size(); ++i)
378 int fd = selarray[i].s;
384 if (fd < 0 || fd >= FD_SETSIZE)
389 if (selarray[i].waitForRead)
393 if (selarray[i].waitForWrite)
401 const float maxWaitSec = LOOP_TIMEOUT;
402 rc =
::select(maxfd+1, &ifds, &ofds, NULL, timer.asTimeval(tv, maxWaitSec));
404 if (rc < 0 && errno == EINTR)
419 }
while ((rc == 0) && !timer.
expired());
430 int availableCount = 0;
432 for (
size_t i = 0; i < selarray.
size(); i++)
434 selarray[i].wasError =
false;
436 if (FD_ISSET(selarray[i].s, &ifds))
438 selarray[i].readAvailable =
true;
443 selarray[i].readAvailable =
false;
446 if (FD_ISSET(selarray[i].s, &ofds))
448 selarray[i].writeAvailable =
true;
453 selarray[i].writeAvailable =
false;
456 availableCount += cval;
460 return availableCount;
501 for (
size_t i = 0; i < selarray.
size(); ++i)
514 for (
size_t i = 0; i < soa.
size(); ++i)
516 if (soa[i].readAvailable)
#define BLOCXX_ASSERT(CON)
BLOCXX_ASSERT works similar to the assert() macro, but instead of calling abort(),...
void push_back(const T &x)
Append an element to the end of the Array.
void reserve(size_type n)
Ensure the capacity is at least the size of a given value.
The AutoPtrVec class provides a simple class for smart pointers to a dynamically allocated array of o...
handle_type get() const
Return handle of resource, retaining ownership.
static void testCancel()
Test if this thread has been cancelled.
A timeout can be absolute, which means that it will happen at the specified DateTime.
static Timeout relative(float seconds)
A TimeoutTimer is used by an algorithm to determine when a timeout has expired.
bool expired() const
Indicates whether the last loop time has exceeded the timeout.
void start()
Meant to be called by timeout functions which loop.
void loop()
Meant to be called by timeout functions which loop, but don't want to reset the interval.
int selectRWSelect(SelectObjectArray &selarray, const Timeout &timeout)
Array< SelectObject > SelectObjectArray
int selectRWPoll(SelectObjectArray &selarray, const Timeout &timeout)
int select(const SelectTypeArray &selarray, UInt32 ms)
Select returns as soon as input is available on any of Select_t objects that are in given array.
const int SELECT_TIMEOUT
The value returned from select when the timeout value has expired.
const int SELECT_NOT_IMPLEMENTED
Used internally, but listed here to prevent conflicts.
int selectRW(SelectObjectArray &selarray, UInt32 ms)
int selectRWEpoll(SelectObjectArray &selarray, const Timeout &timeout)
const int SELECT_ERROR
The value returned from select when any error occurs other than timeout.
Array< Select_t > SelectTypeArray
AutoResource< AutoDescriptorPolicy > AutoDescriptor
An analog of std::auto_ptr for descriptors.
bool waitForRead
Input parameter. Set it to true to indicate that waiting for read availability on s is desired.
bool writeAvailable
Ouput parameter. Will be set to true to indicate that s has become available for writing.
bool waitForWrite
Input parameter. Set it to true to indicate that waiting for write availability on s is desired.
bool readAvailable
Ouput parameter. Will be set to true to indicate that s has become available for reading.