2015-10-18 21:07:23 +03:00
|
|
|
/*
|
2016-01-28 15:07:31 +01:00
|
|
|
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
2015-10-18 21:07:23 +03:00
|
|
|
|
|
|
|
This file is part of libzmq, the ZeroMQ core engine in C++.
|
|
|
|
|
|
|
|
libzmq is free software; you can redistribute it and/or modify it under
|
|
|
|
the terms of the GNU Lesser General Public License (LGPL) as published
|
|
|
|
by the Free Software Foundation; either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
As a special exception, the Contributors give you permission to link
|
|
|
|
this library with independent modules to produce an executable,
|
|
|
|
regardless of the license terms of these independent modules, and to
|
|
|
|
copy and distribute the resulting executable under terms of your choice,
|
|
|
|
provided that you also meet, for each linked independent module, the
|
|
|
|
terms and conditions of the license of that module. An independent
|
|
|
|
module is a module which is not derived from or based on this library.
|
|
|
|
If you modify this library, you must extend this exception to your
|
|
|
|
version of the library.
|
|
|
|
|
|
|
|
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
|
|
|
License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "socket_poller.hpp"
|
|
|
|
#include "err.hpp"
|
|
|
|
|
|
|
|
zmq::socket_poller_t::socket_poller_t () :
|
|
|
|
tag (0xCAFEBABE),
|
2015-10-22 11:12:04 +03:00
|
|
|
need_rebuild (true),
|
|
|
|
use_signaler (false)
|
2016-01-13 15:12:47 +02:00
|
|
|
#if defined ZMQ_POLL_BASED_ON_POLL
|
2015-10-22 11:12:04 +03:00
|
|
|
,
|
|
|
|
pollfds (NULL)
|
|
|
|
#endif
|
2016-01-13 15:12:47 +02:00
|
|
|
{
|
2015-10-18 21:07:23 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
zmq::socket_poller_t::~socket_poller_t ()
|
|
|
|
{
|
|
|
|
// Mark the socket_poller as dead
|
2016-01-13 15:12:47 +02:00
|
|
|
tag = 0xdeadbeef;
|
2015-10-18 21:07:23 +03:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
for (items_t::iterator it = items.begin(); it != items.end(); ++it) {
|
2016-01-13 15:12:47 +02:00
|
|
|
if (it->socket && it->socket->check_tag()) {
|
2015-10-18 21:50:24 +03:00
|
|
|
int thread_safe;
|
|
|
|
size_t thread_safe_size = sizeof(int);
|
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
if (it->socket->getsockopt (ZMQ_THREAD_SAFE, &thread_safe, &thread_safe_size) == 0 && thread_safe)
|
2016-01-13 15:12:47 +02:00
|
|
|
it->socket->remove_signaler (&signaler);
|
2015-10-18 21:50:24 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
#if defined ZMQ_POLL_BASED_ON_POLL
|
|
|
|
if (pollfds) {
|
|
|
|
free (pollfds);
|
|
|
|
pollfds = NULL;
|
2015-10-18 21:07:23 +03:00
|
|
|
}
|
2016-01-13 15:12:47 +02:00
|
|
|
#endif
|
2015-10-18 21:07:23 +03:00
|
|
|
}
|
|
|
|
|
2016-01-13 15:12:47 +02:00
|
|
|
bool zmq::socket_poller_t::check_tag ()
|
2015-10-18 21:07:23 +03:00
|
|
|
{
|
|
|
|
return tag == 0xCAFEBABE;
|
|
|
|
}
|
|
|
|
|
2016-01-13 15:12:47 +02:00
|
|
|
int zmq::socket_poller_t::add (socket_base_t *socket_, void* user_data_, short events_)
|
2015-10-18 21:07:23 +03:00
|
|
|
{
|
2015-10-22 11:12:04 +03:00
|
|
|
for (items_t::iterator it = items.begin (); it != items.end (); ++it) {
|
2015-10-18 21:07:23 +03:00
|
|
|
if (it->socket == socket_) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
2016-01-13 15:12:47 +02:00
|
|
|
}
|
2015-10-18 21:07:23 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int thread_safe;
|
|
|
|
size_t thread_safe_size = sizeof(int);
|
2015-10-22 11:12:04 +03:00
|
|
|
|
|
|
|
if (socket_->getsockopt (ZMQ_THREAD_SAFE, &thread_safe, &thread_safe_size) == -1)
|
2015-10-18 21:07:23 +03:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (thread_safe) {
|
2015-10-22 11:12:04 +03:00
|
|
|
if (socket_->add_signaler (&signaler) == -1)
|
2015-10-18 21:07:23 +03:00
|
|
|
return -1;
|
|
|
|
}
|
2016-01-13 15:12:47 +02:00
|
|
|
|
Style: Fix -Wmissing-field-initializers in socket_poller.cpp
This commit addresses the following warnings reported on gcc 5.2.1. In
the future, this will help reduce the "noise" and help catch warnings
revealing a serious problem.
It was originally introduce in the refactoring associated with
zeromq/libzmq@da2bc60 (Removing zmq_pollfd as it is replaced by zmq_poller).
8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---
/path/to/libzmq/src/socket_poller.cpp: In member function ‘int zmq::socket_poller_t::add(zmq::socket_base_t*, void*, short int)’:
/path/to/libzmq/src/socket_poller.cpp:92:51: warning: missing initializer for member ‘zmq::socket_poller_t::item_t::pollfd_index’ [-Wmissing-field-initializers]
item_t item = {socket_, 0, user_data_, events_};
^
/path/to/libzmq/src/socket_poller.cpp: In member function ‘int zmq::socket_poller_t::add_fd(zmq::fd_t, void*, short int)’:
/path/to/libzmq/src/socket_poller.cpp:108:50: warning: missing initializer for member ‘zmq::socket_poller_t::item_t::pollfd_index’ [-Wmissing-field-initializers]
item_t item = {NULL, fd_, user_data_, events_};
^
8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---
2016-01-30 02:54:43 -05:00
|
|
|
item_t item = {socket_, 0, user_data_, events_
|
|
|
|
#if defined ZMQ_POLL_BASED_ON_POLL
|
|
|
|
,-1
|
|
|
|
#endif
|
|
|
|
};
|
2015-10-22 11:12:04 +03:00
|
|
|
items.push_back (item);
|
2015-10-18 21:07:23 +03:00
|
|
|
need_rebuild = true;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
int zmq::socket_poller_t::add_fd (fd_t fd_, void *user_data_, short events_)
|
2015-10-18 21:07:23 +03:00
|
|
|
{
|
2015-10-22 11:12:04 +03:00
|
|
|
for (items_t::iterator it = items.begin (); it != items.end (); ++it) {
|
2015-10-18 21:07:23 +03:00
|
|
|
if (!it->socket && it->fd == fd_) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
2016-01-13 15:12:47 +02:00
|
|
|
}
|
2015-10-18 21:07:23 +03:00
|
|
|
}
|
|
|
|
|
Style: Fix -Wmissing-field-initializers in socket_poller.cpp
This commit addresses the following warnings reported on gcc 5.2.1. In
the future, this will help reduce the "noise" and help catch warnings
revealing a serious problem.
It was originally introduce in the refactoring associated with
zeromq/libzmq@da2bc60 (Removing zmq_pollfd as it is replaced by zmq_poller).
8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---
/path/to/libzmq/src/socket_poller.cpp: In member function ‘int zmq::socket_poller_t::add(zmq::socket_base_t*, void*, short int)’:
/path/to/libzmq/src/socket_poller.cpp:92:51: warning: missing initializer for member ‘zmq::socket_poller_t::item_t::pollfd_index’ [-Wmissing-field-initializers]
item_t item = {socket_, 0, user_data_, events_};
^
/path/to/libzmq/src/socket_poller.cpp: In member function ‘int zmq::socket_poller_t::add_fd(zmq::fd_t, void*, short int)’:
/path/to/libzmq/src/socket_poller.cpp:108:50: warning: missing initializer for member ‘zmq::socket_poller_t::item_t::pollfd_index’ [-Wmissing-field-initializers]
item_t item = {NULL, fd_, user_data_, events_};
^
8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---
2016-01-30 02:54:43 -05:00
|
|
|
item_t item = {NULL, fd_, user_data_, events_
|
|
|
|
#if defined ZMQ_POLL_BASED_ON_POLL
|
|
|
|
,-1
|
|
|
|
#endif
|
|
|
|
};
|
2015-10-22 11:12:04 +03:00
|
|
|
items.push_back (item);
|
2015-10-18 21:07:23 +03:00
|
|
|
need_rebuild = true;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
int zmq::socket_poller_t::modify (socket_base_t *socket_, short events_)
|
2015-10-21 10:14:36 +03:00
|
|
|
{
|
2015-10-22 11:12:04 +03:00
|
|
|
items_t::iterator it;
|
2015-10-21 10:14:36 +03:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
for (it = items.begin (); it != items.end (); ++it) {
|
2015-10-21 10:14:36 +03:00
|
|
|
if (it->socket == socket_)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
if (it == items.end()) {
|
2015-10-21 10:14:36 +03:00
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
it->events = events_;
|
|
|
|
need_rebuild = true;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
int zmq::socket_poller_t::modify_fd (fd_t fd_, short events_)
|
2015-10-21 10:14:36 +03:00
|
|
|
{
|
2015-10-22 11:12:04 +03:00
|
|
|
items_t::iterator it;
|
2015-10-21 10:14:36 +03:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
for (it = items.begin (); it != items.end (); ++it) {
|
2015-10-21 10:14:36 +03:00
|
|
|
if (!it->socket && it->fd == fd_)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
if (it == items.end()) {
|
2015-10-21 10:14:36 +03:00
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
2016-01-13 15:12:47 +02:00
|
|
|
|
2015-10-21 10:14:36 +03:00
|
|
|
it->events = events_;
|
|
|
|
need_rebuild = true;
|
|
|
|
|
|
|
|
return 0;
|
2016-01-13 15:12:47 +02:00
|
|
|
}
|
2015-10-21 10:14:36 +03:00
|
|
|
|
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
int zmq::socket_poller_t::remove (socket_base_t *socket_)
|
2015-10-18 21:07:23 +03:00
|
|
|
{
|
2015-10-22 11:12:04 +03:00
|
|
|
items_t::iterator it;
|
2015-10-18 21:07:23 +03:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
for (it = items.begin (); it != items.end (); ++it) {
|
2015-10-18 21:07:23 +03:00
|
|
|
if (it->socket == socket_)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
if (it == items.end()) {
|
2015-10-18 21:07:23 +03:00
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
2016-01-13 15:12:47 +02:00
|
|
|
|
2015-10-18 21:07:23 +03:00
|
|
|
int thread_safe;
|
|
|
|
size_t thread_safe_size = sizeof(int);
|
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
if (socket_->getsockopt (ZMQ_THREAD_SAFE, &thread_safe, &thread_safe_size) == -1)
|
2015-10-18 21:07:23 +03:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (thread_safe) {
|
2015-10-22 11:12:04 +03:00
|
|
|
if (socket_->remove_signaler (&signaler) == -1)
|
2015-10-18 21:07:23 +03:00
|
|
|
return -1;
|
|
|
|
}
|
2016-01-13 15:12:47 +02:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
items.erase (it);
|
2016-01-13 15:12:47 +02:00
|
|
|
need_rebuild = true;
|
|
|
|
|
2015-10-18 21:07:23 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
int zmq::socket_poller_t::remove_fd (fd_t fd_)
|
2015-10-18 21:07:23 +03:00
|
|
|
{
|
2015-10-22 11:12:04 +03:00
|
|
|
items_t::iterator it;
|
2015-10-18 21:07:23 +03:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
for (it = items.begin (); it != items.end (); ++it) {
|
2015-10-18 21:07:23 +03:00
|
|
|
if (!it->socket && it->fd == fd_)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
if (it == items.end()) {
|
2015-10-18 21:07:23 +03:00
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
2016-01-13 15:12:47 +02:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
items.erase (it);
|
2015-10-18 21:07:23 +03:00
|
|
|
need_rebuild = true;
|
|
|
|
|
|
|
|
return 0;
|
2015-10-22 11:12:04 +03:00
|
|
|
}
|
2015-10-18 21:07:23 +03:00
|
|
|
|
2016-01-13 15:12:47 +02:00
|
|
|
int zmq::socket_poller_t::rebuild ()
|
2015-10-18 21:07:23 +03:00
|
|
|
{
|
2015-10-22 11:12:04 +03:00
|
|
|
#if defined ZMQ_POLL_BASED_ON_POLL
|
2015-10-18 21:07:23 +03:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
if (pollfds) {
|
|
|
|
free (pollfds);
|
|
|
|
pollfds = NULL;
|
|
|
|
}
|
2015-10-18 21:07:23 +03:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
use_signaler = false;
|
|
|
|
|
|
|
|
poll_size = 0;
|
|
|
|
|
|
|
|
for (items_t::iterator it = items.begin (); it != items.end (); ++it) {
|
|
|
|
if (it->events) {
|
|
|
|
if (it->socket) {
|
|
|
|
int thread_safe;
|
|
|
|
size_t thread_safe_size = sizeof(int);
|
|
|
|
|
|
|
|
if (it->socket->getsockopt (ZMQ_THREAD_SAFE, &thread_safe, &thread_safe_size) == -1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (thread_safe) {
|
|
|
|
if (!use_signaler) {
|
|
|
|
use_signaler = true;
|
|
|
|
poll_size++;
|
2016-01-13 15:12:47 +02:00
|
|
|
}
|
2015-10-22 11:12:04 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
poll_size++;
|
|
|
|
}
|
2016-01-13 15:12:47 +02:00
|
|
|
else
|
|
|
|
poll_size++;
|
2015-10-22 11:12:04 +03:00
|
|
|
}
|
2015-10-18 21:07:23 +03:00
|
|
|
}
|
2016-01-13 15:12:47 +02:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
if (poll_size == 0)
|
|
|
|
return 0;
|
2015-10-18 21:07:23 +03:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
pollfds = (pollfd*) malloc (poll_size * sizeof (pollfd));
|
|
|
|
alloc_assert (pollfds);
|
|
|
|
|
|
|
|
int item_nbr = 0;
|
|
|
|
|
|
|
|
if (use_signaler) {
|
|
|
|
item_nbr = 1;
|
|
|
|
pollfds[0].fd = signaler.get_fd();
|
|
|
|
pollfds[0].events = POLLIN;
|
2015-10-18 21:07:23 +03:00
|
|
|
}
|
|
|
|
|
2016-01-13 15:12:47 +02:00
|
|
|
for (items_t::iterator it = items.begin (); it != items.end (); ++it) {
|
2015-10-22 11:12:04 +03:00
|
|
|
if (it->events) {
|
|
|
|
if (it->socket) {
|
|
|
|
int thread_safe;
|
|
|
|
size_t thread_safe_size = sizeof(int);
|
|
|
|
|
|
|
|
if (it->socket->getsockopt (ZMQ_THREAD_SAFE, &thread_safe, &thread_safe_size) == -1)
|
|
|
|
return -1;
|
|
|
|
|
2016-01-13 15:12:47 +02:00
|
|
|
if (!thread_safe) {
|
2015-10-22 11:12:04 +03:00
|
|
|
size_t fd_size = sizeof (zmq::fd_t);
|
|
|
|
if (it->socket->getsockopt (ZMQ_FD, &pollfds [item_nbr].fd, &fd_size) == -1) {
|
|
|
|
return -1;
|
|
|
|
}
|
2016-01-13 15:12:47 +02:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
pollfds [item_nbr].events = POLLIN;
|
|
|
|
item_nbr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
pollfds [item_nbr].fd = it->fd;
|
|
|
|
pollfds [item_nbr].events =
|
|
|
|
(it->events & ZMQ_POLLIN ? POLLIN : 0) |
|
|
|
|
(it->events & ZMQ_POLLOUT ? POLLOUT : 0) |
|
|
|
|
(it->events & ZMQ_POLLPRI ? POLLPRI : 0);
|
|
|
|
it->pollfd_index = item_nbr;
|
2016-01-13 15:12:47 +02:00
|
|
|
item_nbr++;
|
2015-10-22 11:12:04 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-10-18 21:07:23 +03:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
#elif defined ZMQ_POLL_BASED_ON_SELECT
|
|
|
|
|
|
|
|
FD_ZERO (&pollset_in);
|
|
|
|
FD_ZERO (&pollset_out);
|
|
|
|
FD_ZERO (&pollset_err);
|
|
|
|
|
|
|
|
// Ensure we do not attempt to select () on more than FD_SETSIZE
|
|
|
|
// file descriptors.
|
|
|
|
zmq_assert (items.size () <= FD_SETSIZE);
|
|
|
|
|
|
|
|
poll_size = 0;
|
|
|
|
|
|
|
|
use_signaler = false;
|
|
|
|
|
|
|
|
for (items_t::iterator it = items.begin (); it != items.end (); ++it) {
|
|
|
|
if (it->socket) {
|
|
|
|
int thread_safe;
|
|
|
|
size_t thread_safe_size = sizeof(int);
|
|
|
|
|
|
|
|
if (it->socket->getsockopt (ZMQ_THREAD_SAFE, &thread_safe, &thread_safe_size) == -1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (thread_safe && it->events) {
|
|
|
|
use_signaler = true;
|
|
|
|
FD_SET (signaler.get_fd (), &pollset_in);
|
|
|
|
poll_size = 1;
|
|
|
|
break;
|
|
|
|
}
|
2015-10-18 21:07:23 +03:00
|
|
|
}
|
|
|
|
}
|
2015-10-22 11:12:04 +03:00
|
|
|
|
|
|
|
maxfd = 0;
|
|
|
|
|
|
|
|
// Build the fd_sets for passing to select ().
|
|
|
|
for (items_t::iterator it = items.begin (); it != items.end (); ++it) {
|
|
|
|
if (it->events) {
|
|
|
|
// If the poll item is a 0MQ socket we are interested in input on the
|
|
|
|
// notification file descriptor retrieved by the ZMQ_FD socket option.
|
|
|
|
if (it->socket) {
|
|
|
|
int thread_safe;
|
|
|
|
size_t thread_safe_size = sizeof(int);
|
|
|
|
|
|
|
|
if (it->socket->getsockopt (ZMQ_THREAD_SAFE, &thread_safe, &thread_safe_size) == -1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!thread_safe) {
|
|
|
|
zmq::fd_t notify_fd;
|
|
|
|
size_t fd_size = sizeof (zmq::fd_t);
|
|
|
|
if (it->socket->getsockopt (ZMQ_FD, ¬ify_fd, &fd_size) == -1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
FD_SET (notify_fd, &pollset_in);
|
|
|
|
if (maxfd < notify_fd)
|
2016-01-13 15:12:47 +02:00
|
|
|
maxfd = notify_fd;
|
2015-10-22 11:12:04 +03:00
|
|
|
|
2016-01-13 15:12:47 +02:00
|
|
|
poll_size++;
|
2015-10-22 11:12:04 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Else, the poll item is a raw file descriptor. Convert the poll item
|
|
|
|
// events to the appropriate fd_sets.
|
|
|
|
else {
|
|
|
|
if (it->events & ZMQ_POLLIN)
|
|
|
|
FD_SET (it->fd, &pollset_in);
|
|
|
|
if (it->events & ZMQ_POLLOUT)
|
|
|
|
FD_SET (it->fd, &pollset_out);
|
|
|
|
if (it->events & ZMQ_POLLERR)
|
|
|
|
FD_SET (it->fd, &pollset_err);
|
|
|
|
if (maxfd < it->fd)
|
|
|
|
maxfd = it->fd;
|
|
|
|
|
|
|
|
poll_size++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
need_rebuild = false;
|
2015-10-18 21:07:23 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
int zmq::socket_poller_t::wait (zmq::socket_poller_t::event_t *event_, long timeout_)
|
2015-10-18 21:07:23 +03:00
|
|
|
{
|
2015-10-22 11:12:04 +03:00
|
|
|
if (need_rebuild)
|
|
|
|
if (rebuild () == -1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
#if defined ZMQ_POLL_BASED_ON_POLL
|
|
|
|
if (unlikely (poll_size == 0)) {
|
|
|
|
if (timeout_ == 0)
|
|
|
|
return 0;
|
|
|
|
#if defined ZMQ_HAVE_WINDOWS
|
|
|
|
Sleep (timeout_ > 0 ? timeout_ : INFINITE);
|
|
|
|
return 0;
|
|
|
|
#elif defined ZMQ_HAVE_ANDROID
|
|
|
|
usleep (timeout_ * 1000);
|
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
return usleep (timeout_ * 1000);
|
|
|
|
#endif
|
2015-10-18 21:07:23 +03:00
|
|
|
}
|
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
zmq::clock_t clock;
|
|
|
|
uint64_t now = 0;
|
|
|
|
uint64_t end = 0;
|
2016-01-13 15:12:47 +02:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
bool first_pass = true;
|
|
|
|
|
|
|
|
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, poll_size, timeout);
|
|
|
|
if (rc == -1 && errno == EINTR) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
errno_assert (rc >= 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Receive the signal from pollfd
|
|
|
|
if (use_signaler && pollfds[0].revents & POLLIN)
|
|
|
|
signaler.recv ();
|
|
|
|
|
|
|
|
// Check for the events.
|
|
|
|
for (items_t::iterator it = items.begin (); it != items.end (); ++it) {
|
|
|
|
|
|
|
|
// The poll item is a 0MQ socket. Retrieve pending events
|
|
|
|
// using the ZMQ_EVENTS socket option.
|
|
|
|
if (it->socket) {
|
|
|
|
size_t events_size = sizeof (uint32_t);
|
|
|
|
uint32_t events;
|
|
|
|
if (it->socket->getsockopt (ZMQ_EVENTS, &events, &events_size) == -1) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (it->events & events) {
|
|
|
|
event_->socket = it->socket;
|
|
|
|
event_->user_data = it->user_data;
|
|
|
|
event_->events = it->events & events;
|
|
|
|
|
|
|
|
// If there is event to return, we can exit immediately.
|
|
|
|
return 0;
|
2016-01-13 15:12:47 +02:00
|
|
|
}
|
2015-10-22 11:12:04 +03:00
|
|
|
}
|
|
|
|
// Else, the poll item is a raw file descriptor, simply convert
|
|
|
|
// the events to zmq_pollitem_t-style format.
|
|
|
|
else {
|
|
|
|
short revents = pollfds [it->pollfd_index].revents;
|
2016-01-13 15:12:47 +02:00
|
|
|
short events = 0;
|
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
if (revents & POLLIN)
|
|
|
|
events |= ZMQ_POLLIN;
|
|
|
|
if (revents & POLLOUT)
|
|
|
|
events |= ZMQ_POLLOUT;
|
|
|
|
if (revents & POLLPRI)
|
|
|
|
events |= ZMQ_POLLPRI;
|
|
|
|
if (revents & ~(POLLIN | POLLOUT | POLLPRI))
|
|
|
|
events |= ZMQ_POLLERR;
|
|
|
|
|
|
|
|
if (events) {
|
|
|
|
event_->socket = NULL;
|
|
|
|
event_->user_data = it->user_data;
|
|
|
|
event_->fd = it->fd;
|
|
|
|
event_->events = events;
|
|
|
|
|
|
|
|
// If there is event to return, we can exit immediately.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If timeout is zero, exit immediately whether there are events or not.
|
|
|
|
if (timeout_ == 0)
|
|
|
|
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;
|
2015-10-18 21:07:23 +03:00
|
|
|
}
|
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
errno = ETIMEDOUT;
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
#elif defined ZMQ_POLL_BASED_ON_SELECT
|
|
|
|
|
|
|
|
if (unlikely (poll_size == 0)) {
|
|
|
|
if (timeout_ == 0)
|
|
|
|
return 0;
|
|
|
|
#if defined ZMQ_HAVE_WINDOWS
|
|
|
|
Sleep (timeout_ > 0 ? timeout_ : INFINITE);
|
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
return usleep (timeout_ * 1000);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
zmq::clock_t clock;
|
|
|
|
uint64_t now = 0;
|
|
|
|
uint64_t end = 0;
|
|
|
|
|
2016-01-13 15:12:47 +02:00
|
|
|
bool first_pass = true;
|
2015-10-22 11:12:04 +03:00
|
|
|
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 ZMQ_HAVE_WINDOWS
|
|
|
|
int rc = select (0, &inset, &outset, &errset, ptimeout);
|
|
|
|
if (unlikely (rc == SOCKET_ERROR)) {
|
|
|
|
errno = zmq::wsa_error_to_errno (WSAGetLastError ());
|
|
|
|
wsa_assert (errno == ENOTSOCK);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
int rc = select (maxfd + 1, &inset, &outset, &errset, ptimeout);
|
|
|
|
if (unlikely (rc == -1)) {
|
|
|
|
errno_assert (errno == EINTR || errno == EBADF);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (use_signaler && FD_ISSET (signaler.get_fd (), &inset))
|
|
|
|
signaler.recv ();
|
|
|
|
|
|
|
|
// Check for the events.
|
|
|
|
for (items_t::iterator it = items.begin (); it != items.end (); ++it) {
|
|
|
|
|
|
|
|
// The poll item is a 0MQ socket. Retrieve pending events
|
|
|
|
// using the ZMQ_EVENTS socket option.
|
|
|
|
if (it->socket) {
|
|
|
|
size_t events_size = sizeof (uint32_t);
|
|
|
|
uint32_t events;
|
|
|
|
if (it->socket->getsockopt (ZMQ_EVENTS, &events, &events_size) == -1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (it->events & events) {
|
|
|
|
event_->socket = it->socket;
|
|
|
|
event_->user_data = it->user_data;
|
|
|
|
event_->events = it->events & events;
|
|
|
|
|
|
|
|
// If there is event to return, we can exit immediately.
|
|
|
|
return 0;
|
2016-01-13 15:12:47 +02:00
|
|
|
}
|
2015-10-22 11:12:04 +03:00
|
|
|
}
|
|
|
|
// Else, the poll item is a raw file descriptor, simply convert
|
|
|
|
// the events to zmq_pollitem_t-style format.
|
|
|
|
else {
|
|
|
|
short events = 0;
|
|
|
|
|
|
|
|
if (FD_ISSET (it->fd, &inset))
|
|
|
|
events |= ZMQ_POLLIN;
|
|
|
|
if (FD_ISSET (it->fd, &outset))
|
|
|
|
events |= ZMQ_POLLOUT;
|
|
|
|
if (FD_ISSET (it->fd, &errset))
|
|
|
|
events |= ZMQ_POLLERR;
|
2016-01-13 15:12:47 +02:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
if (events) {
|
|
|
|
event_->socket = NULL;
|
|
|
|
event_->user_data = it->user_data;
|
|
|
|
event_->fd = it->fd;
|
|
|
|
event_->events = events;
|
|
|
|
|
|
|
|
// If there is event to return, we can exit immediately.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-10-18 21:07:23 +03:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
// If timeout is zero, exit immediately whether there are events or not.
|
|
|
|
if (timeout_ == 0)
|
|
|
|
break;
|
2015-10-18 21:07:23 +03:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
// 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;
|
|
|
|
}
|
2015-10-18 21:07:23 +03:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
// 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;
|
|
|
|
}
|
2015-10-18 21:07:23 +03:00
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
// Find out whether timeout have expired.
|
|
|
|
now = clock.now_ms ();
|
|
|
|
if (now >= end)
|
|
|
|
break;
|
2015-10-18 21:07:23 +03:00
|
|
|
}
|
|
|
|
|
2015-10-22 11:12:04 +03:00
|
|
|
errno = ETIMEDOUT;
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
#else
|
|
|
|
// Exotic platforms that support neither poll() nor select().
|
|
|
|
errno = ENOTSUP;
|
|
|
|
return -1;
|
|
|
|
#endif
|
2015-10-18 21:07:23 +03:00
|
|
|
}
|