summaryrefslogtreecommitdiff
path: root/src/xs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/xs.cpp')
-rw-r--r--src/xs.cpp385
1 files changed, 2 insertions, 383 deletions
diff --git a/src/xs.cpp b/src/xs.cpp
index 7160da9..a4ed3a1 100644
--- a/src/xs.cpp
+++ b/src/xs.cpp
@@ -21,29 +21,6 @@
#include "platform.hpp"
-#if defined XS_FORCE_SELECT
-#define XS_POLL_BASED_ON_SELECT
-#elif defined XS_FORCE_POLL
-#define XS_POLL_BASED_ON_POLL
-#elif defined XS_HAVE_LINUX || defined XS_HAVE_FREEBSD ||\
- defined XS_HAVE_OPENBSD || defined XS_HAVE_SOLARIS ||\
- defined XS_HAVE_OSX || defined XS_HAVE_QNXNTO ||\
- defined XS_HAVE_HPUX || defined XS_HAVE_AIX ||\
- defined XS_HAVE_NETBSD
-#define XS_POLL_BASED_ON_POLL
-#elif defined XS_HAVE_WINDOWS || defined XS_HAVE_OPENVMS ||\
- defined XS_HAVE_CYGWIN
-#define XS_POLL_BASED_ON_SELECT
-#endif
-
-// On AIX platform, poll.h has to be included first to get consistent
-// definition of pollfd structure (AIX uses 'reqevents' and 'retnevents'
-// instead of 'events' and 'revents' and defines macros to map from POSIX-y
-// names to AIX-specific names).
-#if defined XS_POLL_BASED_ON_POLL
-#include <poll.h>
-#endif
-
#if defined XS_HAVE_WINDOWS
#include "windows.hpp"
#else
@@ -59,16 +36,12 @@
#include "stdint.hpp"
#include "config.hpp"
#include "likely.hpp"
-#include "clock.hpp"
+#include "upoll.hpp"
#include "ctx.hpp"
#include "err.hpp"
#include "msg.hpp"
#include "fd.hpp"
-#if !defined XS_HAVE_WINDOWS
-#include <unistd.h>
-#endif
-
#if defined XS_HAVE_OPENPGM
#define __PGM_WININT_H__
#include <pgm/pgm.h>
@@ -393,355 +366,7 @@ int xs_getmsgopt (xs_msg_t *msg_, int option_, void *optval_,
int xs_poll (xs_pollitem_t *items_, int nitems_, long timeout_)
{
-#if defined XS_POLL_BASED_ON_POLL
- if (unlikely (nitems_ < 0)) {
- errno = EINVAL;
- return -1;
- }
- if (unlikely (nitems_ == 0)) {
- if (timeout_ == 0)
- return 0;
-#if defined XS_HAVE_WINDOWS
- Sleep (timeout_ > 0 ? timeout_ : INFINITE);
- return 0;
-#elif defined XS_HAVE_ANDROID
- usleep (timeout_ * 1000);
- return 0;
-#else
- return usleep (timeout_ * 1000);
-#endif
- }
-
- if (!items_) {
- errno = EFAULT;
- return -1;
- }
-
- xs::clock_t clock;
- uint64_t now = 0;
- uint64_t end = 0;
-
- pollfd *pollfds = (pollfd*) malloc (nitems_ * sizeof (pollfd));
- alloc_assert (pollfds);
-
- // Build pollset for poll () system call.
- for (int i = 0; i != nitems_; i++) {
-
- // If the poll item is a Crossroads socket, we poll on the file
- // descriptor retrieved by the XS_FD socket option.
- if (items_ [i].socket) {
- size_t xs_fd_size = sizeof (xs::fd_t);
- if (xs_getsockopt (items_ [i].socket, XS_FD, &pollfds [i].fd,
- &xs_fd_size) == -1) {
- free (pollfds);
- return -1;
- }
- pollfds [i].events = items_ [i].events ? POLLIN : 0;
- }
- // Else, the poll item is a raw file descriptor. Just convert the
- // events to normal POLLIN/POLLOUT for poll ().
- else {
- pollfds [i].fd = items_ [i].fd;
- pollfds [i].events =
- (items_ [i].events & XS_POLLIN ? POLLIN : 0) |
- (items_ [i].events & XS_POLLOUT ? POLLOUT : 0);
- }
- }
-
- bool first_pass = true;
- int nevents = 0;
-
- while (true) {
-
- // Compute the timeout for the subsequent poll.
- int timeout;
- if (first_pass)
- timeout = 0;
- else if (timeout_ < 0)
- timeout = -1;
- else
- timeout = end - now;
-
- // Wait for events.
- while (true) {
- int rc = poll (pollfds, nitems_, timeout);
- if (rc == -1 && errno == EINTR) {
- free (pollfds);
- return -1;
- }
- errno_assert (rc >= 0);
- break;
- }
-
- // Check for the events.
- for (int i = 0; i != nitems_; i++) {
-
- items_ [i].revents = 0;
-
- // The poll item is a Crossroads socket. Retrieve pending events
- // using the XS_EVENTS socket option.
- if (items_ [i].socket) {
- size_t xs_events_size = sizeof (uint32_t);
- uint32_t xs_events;
- if (xs_getsockopt (items_ [i].socket, XS_EVENTS, &xs_events,
- &xs_events_size) == -1) {
- free (pollfds);
- return -1;
- }
- if ((items_ [i].events & XS_POLLOUT) &&
- (xs_events & XS_POLLOUT))
- items_ [i].revents |= XS_POLLOUT;
- if ((items_ [i].events & XS_POLLIN) &&
- (xs_events & XS_POLLIN))
- items_ [i].revents |= XS_POLLIN;
- }
- // Else, the poll item is a raw file descriptor, simply convert
- // the events to xs_pollitem_t-style format.
- else {
- if (pollfds [i].revents & POLLIN)
- items_ [i].revents |= XS_POLLIN;
- if (pollfds [i].revents & POLLOUT)
- items_ [i].revents |= XS_POLLOUT;
- if (pollfds [i].revents & ~(POLLIN | POLLOUT))
- items_ [i].revents |= XS_POLLERR;
- }
-
- if (items_ [i].revents)
- nevents++;
- }
-
- // If timout is zero, exit immediately whether there are events or not.
- if (timeout_ == 0)
- break;
-
- // If there are events to return, we can exit immediately.
- if (nevents)
- break;
-
- // At this point we are meant to wait for events but there are none.
- // If timeout is infinite we can just loop until we get some events.
- if (timeout_ < 0) {
- if (first_pass)
- first_pass = false;
- continue;
- }
-
- // The timeout is finite and there are no events. In the first pass
- // we get a timestamp of when the polling have begun. (We assume that
- // first pass have taken negligible time). We also compute the time
- // when the polling should time out.
- if (first_pass) {
- now = clock.now_ms ();
- end = now + timeout_;
- if (now == end)
- break;
- first_pass = false;
- continue;
- }
-
- // Find out whether timeout have expired.
- now = clock.now_ms ();
- if (now >= end)
- break;
- }
-
- free (pollfds);
- return nevents;
-
-#elif defined XS_POLL_BASED_ON_SELECT
-
- if (unlikely (nitems_ < 0)) {
- errno = EINVAL;
- return -1;
- }
- if (unlikely (nitems_ == 0)) {
- if (timeout_ == 0)
- return 0;
-#if defined XS_HAVE_WINDOWS
- Sleep (timeout_ > 0 ? timeout_ : INFINITE);
- return 0;
-#else
- return usleep (timeout_ * 1000);
-#endif
- }
-
- if (!items_) {
- errno = EFAULT;
- return -1;
- }
-
- xs::clock_t clock;
- uint64_t now = 0;
- uint64_t end = 0;
-
- // Ensure we do not attempt to select () on more than FD_SETSIZE
- // file descriptors.
- xs_assert (nitems_ <= FD_SETSIZE);
-
- fd_set pollset_in;
- FD_ZERO (&pollset_in);
- fd_set pollset_out;
- FD_ZERO (&pollset_out);
- fd_set pollset_err;
- FD_ZERO (&pollset_err);
-
- xs::fd_t maxfd = 0;
-
- // Build the fd_sets for passing to select ().
- for (int i = 0; i != nitems_; i++) {
-
- // If the poll item is a Crossroads socket we are interested in input
- // on the notification file descriptor retrieved by the XS_FD socket
- // option.
- if (items_ [i].socket) {
- size_t xs_fd_size = sizeof (xs::fd_t);
- xs::fd_t notify_fd;
- if (xs_getsockopt (items_ [i].socket, XS_FD, &notify_fd,
- &xs_fd_size) == -1)
- return -1;
- if (items_ [i].events) {
- FD_SET (notify_fd, &pollset_in);
- if (maxfd < notify_fd)
- maxfd = notify_fd;
- }
- }
- // Else, the poll item is a raw file descriptor. Convert the poll item
- // events to the appropriate fd_sets.
- else {
- if (items_ [i].events & XS_POLLIN)
- FD_SET (items_ [i].fd, &pollset_in);
- if (items_ [i].events & XS_POLLOUT)
- FD_SET (items_ [i].fd, &pollset_out);
- if (items_ [i].events & XS_POLLERR)
- FD_SET (items_ [i].fd, &pollset_err);
- if (maxfd < items_ [i].fd)
- maxfd = items_ [i].fd;
- }
- }
-
- bool first_pass = true;
- int nevents = 0;
- fd_set inset, outset, errset;
-
- while (true) {
-
- // Compute the timeout for the subsequent poll.
- timeval timeout;
- timeval *ptimeout;
- if (first_pass) {
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
- ptimeout = &timeout;
- }
- else if (timeout_ < 0)
- ptimeout = NULL;
- else {
- timeout.tv_sec = (long) ((end - now) / 1000);
- timeout.tv_usec = (long) ((end - now) % 1000 * 1000);
- ptimeout = &timeout;
- }
-
- // Wait for events. Ignore interrupts if there's infinite timeout.
- while (true) {
- memcpy (&inset, &pollset_in, sizeof (fd_set));
- memcpy (&outset, &pollset_out, sizeof (fd_set));
- memcpy (&errset, &pollset_err, sizeof (fd_set));
-#if defined XS_HAVE_WINDOWS
- int rc = select (0, &inset, &outset, &errset, ptimeout);
- if (unlikely (rc == SOCKET_ERROR)) {
- xs::wsa_error_to_errno ();
- if (errno == ENOTSOCK)
- return -1;
- wsa_assert (false);
- }
-#else
- int rc = select (maxfd + 1, &inset, &outset, &errset, ptimeout);
- if (unlikely (rc == -1)) {
- if (errno == EINTR || errno == EBADF)
- return -1;
- errno_assert (false);
- }
-#endif
- break;
- }
-
- // Check for the events.
- for (int i = 0; i != nitems_; i++) {
-
- items_ [i].revents = 0;
-
- // The poll item is a Crossroads socket. Retrieve pending events
- // using the XS_EVENTS socket option.
- if (items_ [i].socket) {
- size_t xs_events_size = sizeof (uint32_t);
- uint32_t xs_events;
- if (xs_getsockopt (items_ [i].socket, XS_EVENTS, &xs_events,
- &xs_events_size) == -1)
- return -1;
- if ((items_ [i].events & XS_POLLOUT) &&
- (xs_events & XS_POLLOUT))
- items_ [i].revents |= XS_POLLOUT;
- if ((items_ [i].events & XS_POLLIN) &&
- (xs_events & XS_POLLIN))
- items_ [i].revents |= XS_POLLIN;
- }
- // Else, the poll item is a raw file descriptor, simply convert
- // the events to xs_pollitem_t-style format.
- else {
- if (FD_ISSET (items_ [i].fd, &inset))
- items_ [i].revents |= XS_POLLIN;
- if (FD_ISSET (items_ [i].fd, &outset))
- items_ [i].revents |= XS_POLLOUT;
- if (FD_ISSET (items_ [i].fd, &errset))
- items_ [i].revents |= XS_POLLERR;
- }
-
- if (items_ [i].revents)
- nevents++;
- }
-
- // If timout is zero, exit immediately whether there are events or not.
- if (timeout_ == 0)
- break;
-
- // If there are events to return, we can exit immediately.
- if (nevents)
- break;
-
- // At this point we are meant to wait for events but there are none.
- // If timeout is infinite we can just loop until we get some events.
- if (timeout_ < 0) {
- if (first_pass)
- first_pass = false;
- continue;
- }
-
- // The timeout is finite and there are no events. In the first pass
- // we get a timestamp of when the polling have begun. (We assume that
- // first pass have taken negligible time). We also compute the time
- // when the polling should time out.
- if (first_pass) {
- now = clock.now_ms ();
- end = now + timeout_;
- if (now == end)
- break;
- first_pass = false;
- continue;
- }
-
- // Find out whether timeout have expired.
- now = clock.now_ms ();
- if (now >= end)
- break;
- }
-
- return nevents;
-
-#else
- // Exotic platforms that support neither poll() nor select().
- errno = ENOTSUP;
- return -1;
-#endif
+ return xs::upoll (items_, nitems_, timeout_);
}
int xs_errno ()
@@ -749,10 +374,4 @@ int xs_errno ()
return errno;
}
-#if defined XS_POLL_BASED_ON_SELECT
-#undef XS_POLL_BASED_ON_SELECT
-#endif
-#if defined XS_POLL_BASED_ON_POLL
-#undef XS_POLL_BASED_ON_POLL
-#endif