123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- /*
- Copyright (c) 2013 Martin Sustrik All rights reserved.
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"),
- to deal in the Software without restriction, including without limitation
- the rights to use, copy, modify, merge, publish, distribute, sublicense,
- and/or sell copies of the Software, and to permit persons to whom
- the Software is furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- IN THE SOFTWARE.
- */
- #include "../nn.h"
- #if defined NN_HAVE_WINDOWS
- #include "../utils/win.h"
- #include "../utils/fast.h"
- #include "../utils/sleep.h"
- #include "../utils/err.h"
- int nn_poll (struct nn_pollfd *fds, int nfds, int timeout)
- {
- int rc;
- int i;
- fd_set fdset;
- SOCKET fd;
- int res;
- size_t sz;
- struct timeval tv;
- /* Fill in the fdset, as appropriate. */
- FD_ZERO (&fdset);
- for (i = 0; i != nfds; ++i) {
- if (fds [i].events & NN_POLLIN) {
- sz = sizeof (fd);
- rc = nn_getsockopt (fds [i].fd, NN_SOL_SOCKET, NN_RCVFD, &fd, &sz);
- if (nn_slow (rc < 0)) {
- errno = -rc;
- return -1;
- }
- nn_assert (sz == sizeof (fd));
- FD_SET (fd, &fdset);
- }
- if (fds [i].events & NN_POLLOUT) {
- sz = sizeof (fd);
- rc = nn_getsockopt (fds [i].fd, NN_SOL_SOCKET, NN_SNDFD, &fd, &sz);
- if (nn_slow (rc < 0)) {
- errno = -rc;
- return -1;
- }
- nn_assert (sz == sizeof (fd));
- FD_SET (fd, &fdset);
- }
- }
- /* Do the polling itself. */
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = timeout % 1000 * 1000;
- if (nn_fast (nfds)) {
- rc = select (-1, &fdset, NULL, NULL, &tv);
- if (nn_slow (rc == 0))
- return 0;
- if (nn_slow (rc == SOCKET_ERROR)) {
- errno = nn_err_wsa_to_posix (WSAGetLastError ());
- return -1;
- }
- }
- else {
- /* POSIX platforms will sleep until timeout is expired,
- so let's do the same on Windows. */
- if (timeout > 0)
- nn_sleep(timeout);
- return 0;
- }
- /* Move the results from fdset to the nanomsg pollset. */
- res = 0;
- for (i = 0; i != nfds; ++i) {
- fds [i].revents = 0;
- if (fds [i].events & NN_POLLIN) {
- sz = sizeof (fd);
- rc = nn_getsockopt (fds [i].fd, NN_SOL_SOCKET, NN_RCVFD, &fd, &sz);
- if (nn_slow (rc < 0)) {
- errno = -rc;
- return -1;
- }
- nn_assert (sz == sizeof (fd));
- if (FD_ISSET (fd, &fdset))
- fds [i].revents |= NN_POLLIN;
- }
- if (fds [i].events & NN_POLLOUT) {
- sz = sizeof (fd);
- rc = nn_getsockopt (fds [i].fd, NN_SOL_SOCKET, NN_SNDFD, &fd, &sz);
- if (nn_slow (rc < 0)) {
- errno = -rc;
- return -1;
- }
- nn_assert (sz == sizeof (fd));
- if (FD_ISSET (fd, &fdset))
- fds [i].revents |= NN_POLLOUT;
- }
- if (fds [i].revents)
- ++res;
- }
- return res;
- }
- #else
- #include "../utils/alloc.h"
- #include "../utils/fast.h"
- #include "../utils/err.h"
- #include <poll.h>
- #include <stddef.h>
- int nn_poll (struct nn_pollfd *fds, int nfds, int timeout)
- {
- int rc;
- int i;
- int pos;
- int fd;
- int res;
- size_t sz;
- struct pollfd *pfd;
- /* Construct a pollset to be used with OS-level 'poll' function. */
- pfd = nn_alloc (sizeof (struct pollfd) * nfds * 2, "pollset");
- alloc_assert (pfd);
- pos = 0;
- for (i = 0; i != nfds; ++i) {
- if (fds [i].events & NN_POLLIN) {
- sz = sizeof (fd);
- rc = nn_getsockopt (fds [i].fd, NN_SOL_SOCKET, NN_RCVFD, &fd, &sz);
- if (nn_slow (rc < 0)) {
- nn_free (pfd);
- errno = -rc;
- return -1;
- }
- nn_assert (sz == sizeof (fd));
- pfd [pos].fd = fd;
- pfd [pos].events = POLLIN;
- ++pos;
- }
- if (fds [i].events & NN_POLLOUT) {
- sz = sizeof (fd);
- rc = nn_getsockopt (fds [i].fd, NN_SOL_SOCKET, NN_SNDFD, &fd, &sz);
- if (nn_slow (rc < 0)) {
- nn_free (pfd);
- errno = -rc;
- return -1;
- }
- nn_assert (sz == sizeof (fd));
- pfd [pos].fd = fd;
- pfd [pos].events = POLLIN;
- ++pos;
- }
- }
- /* Do the polling itself. */
- rc = poll (pfd, pos, timeout);
- if (nn_slow (rc <= 0)) {
- res = errno;
- nn_free (pfd);
- errno = res;
- return rc;
- }
- /* Move the results from OS-level poll to nn_poll's pollset. */
- res = 0;
- pos = 0;
- for (i = 0; i != nfds; ++i) {
- fds [i].revents = 0;
- if (fds [i].events & NN_POLLIN) {
- if (pfd [pos].revents & POLLIN)
- fds [i].revents |= NN_POLLIN;
- ++pos;
- }
- if (fds [i].events & NN_POLLOUT) {
- if (pfd [pos].revents & POLLIN)
- fds [i].revents |= NN_POLLOUT;
- ++pos;
- }
- if (fds [i].revents)
- ++res;
- }
- nn_free (pfd);
- return res;
- }
- #endif
|