Merge pull request #3096 from sigiesec/add-poller-docs

Add poller docs
This commit is contained in:
Luca Boccassi 2018-05-14 11:10:10 +01:00 committed by GitHub
commit 54aff77475
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 314 additions and 8 deletions

View File

@ -142,7 +142,10 @@ Monitoring socket events::
0MQ provides a mechanism for applications to multiplex input/output events over
a set containing both 0MQ sockets and standard sockets. This mechanism mirrors
the standard _poll()_ system call, and is described in detail in
linkzmq:zmq_poll[3].
linkzmq:zmq_poll[3]. This API is deprecated, however.
There is a new DRAFT API with multiple zmq_poller_* function, which is described
in linkzmq:zmq_poller[3].
Transports

269
doc/zmq_poller.txt Normal file
View File

@ -0,0 +1,269 @@
zmq_poller(3)
===========
NAME
----
zmq_poller - input/output multiplexing
SYNOPSIS
--------
*void *zmq_poller_new (void);*
*int zmq_poller_destroy (void **'poller_p');*
*int zmq_poller_add (void *'poller', void *'socket', void *'user_data', short 'events');
*int zmq_poller_modify (void *'poller', void *'socket', short 'events');*
*int zmq_poller_remove (void *'poller', void *'socket');*
*int zmq_poller_add_fd (void *'poller', int 'fd', void *'user_data', short 'events');*
*int zmq_poller_modify_fd (void *'poller', int 'fd', short 'events');*
*int zmq_poller_remove_fd (void *'poller', int 'fd');*
*int zmq_poller_wait_all (void *'poller',
zmq_poller_event_t *'events',
int 'n_events',
long 'timeout');*
DESCRIPTION
-----------
The _zmq_poller_*_ functions provide a mechanism for applications to multiplex
input/output events in a level-triggered fashion over a set of sockets.
_zmq_poller_new_ and _zmq_poller_destroy_ manage the lifetime of a poller
instance. _zmq_poller_new_ creates and returns a new poller instance, while
_zmq_poller_destroy_ destroys it. A pointer to a valid poller must be passed
as the _poller_p_ argument of _zmq_poller_destroy_. In particular,
_zmq_poller_destroy_ may not be called multiple times for the same poller
instance. _zmq_poller_destroy_ sets the passed pointer to NULL in case of a
successful execution. _zmq_poller_destroy_ implicitly unregisters all
registered sockets and file descriptors.
_zmq_poller_add_, _zmq_poller_modify_ and _zmq_poller_remove_ manage the 0MQ
sockets registered with a poller.
_zmq_poller_add_ registers a new _socket_ with a given _poller_. Both _poller_
and _socket_ must point to valid 0MQ objects. The _events_ parameter specifies
which event types the client wants to subscribe to. It is legal to specify no
events (i.e. 0), and activate them later with _zmq_poller_modify_.
In addition, _user_data_ may be specified, which is not used by the poller, but
passed back to the caller when an event was signalled in a call to
_zmq_poller_wait_ or _zmq_poller_wait_all_. _user_data_ may be NULL. If it is
not NULL, it must be a valid pointer. Otherwise, behaviour is undefined.
_zmq_poller_add_ may not be called multiple times for the same socket
(unless _zmq_poller_remove_ has been called for that socket).
_zmq_poller_modify_ modifies the subscribed events for a socket. It is
legal to specify no events (i.e. 0) to disable events temporarily, and
reactivate them later with another call to _zmq_poller_modify_.
_zmq_poller_remove_ removes a socket registration completely.
_zmq_poller_remove_ must be called before a socket is closed with _zmq_close_.
Note that it is not necessary to call _zmq_poller_remove_ for any socket
before calling _zmq_poller_destroy_.
Also note that calling _zmq_poller_remove_ is not equivalent to calling
_zmq_poller_modify_ with no events. _zmq_poller_modify_ does not free resources
associated with the socket registration, and requires that the _socket_
remains valid.
_zmq_poller_add_fd_, _zmq_poller_modify_fd_ and _zmq_poller_remove_fd_ are
analogous to the previous functions but manage regular file descriptiors
registered with a poller. On Windows, these functions can only be used with
WinSock sockets.
In the following, 0MQ sockets added with _zmq_poller_add_ and file descriptors
added with _zmq_poller_add_fd_ are referred to as 'registered objects'.
The *zmq_poller_event_t* structure is defined as follows:
["literal", subs="quotes"]
typedef struct
{
void *socket;
#if defined _WIN32
SOCKET fd;
#else
int fd;
#endif
void *user_data;
short events;
} zmq_poller_event_t;
For each registered object, _zmq_poller_wait_all()_ shall examine the
registered objects for the event(s) currently registered.
If none of the registered events have occurred, _zmq_poller_wait_all_ shall
wait 'timeout' milliseconds for an event to occur on any of the registered
objects. If the value of 'timeout' is `0`, _zmq_poller_wait_all_ shall
return immediately. If the value of 'timeout' is `-1`, _zmq_poller_wait_all_
shall block indefinitely until one event has occurred on any of the
registered objects.
The 'events' argument _zmq_poller_wait_all_ must be a pointer to an array of
at least 'n_events' elements. Behaviour is undefined if 'events' does not point
to an array of at least 'n_events' elements.
_zmq_poller_wait_all_ returns at most 'n_events' events. If more than
'n_events' events were signalled, only an unspecified subset of the signalled
events is returned through 'events'.
A caller is advised to ensure that 'n_events' is equal to the number of
registered objects. Otherwise, a livelock situation may result: If more than
'n_events' registered objects have an active event on each call to
_zmq_poller_wait_all_, it might happen that the same subset of registered
objects is always returned, and the caller never notices the events on the
others.
_zmq_poller_wait_all_ returns the number of valid elements. The valid elements
are placed in positions '0' to 'n_events - 1' in the 'events' array. All
members of a valid element are set to valid values by _zmq_poller_wait_all_.
The client does therefore not need to initialize the contents of the events
array before a call to _zmq_poller_wait_all_. It is unspecified whether the
the remaining elements of 'events' are written to by _zmq_poller_wait_all_.
EVENT TYPES
-----------
The 'events' parameter of _zmq_poller_add_ and _zmq_poller_modify_, and the
'events' member of the zmq_poller_event_t structure are bit masks constructed
by OR'ing a combination of the following event flags:
*ZMQ_POLLIN*::
For 0MQ sockets, at least one message may be received from the 'socket' without
blocking. For standard sockets this is equivalent to the 'POLLIN' flag of the
_poll()_ system call and generally means that at least one byte of data may be
read from 'fd' without blocking.
*ZMQ_POLLOUT*::
For 0MQ sockets, at least one message may be sent to the 'socket' without
blocking. For standard sockets this is equivalent to the 'POLLOUT' flag of the
_poll()_ system call and generally means that at least one byte of data may be
written to 'fd' without blocking.
*ZMQ_POLLERR*::
For 0MQ sockets this flag has no effect on the _zmq_poller_add_ and
_zmq_poller_modify_ functions, and is never set in the
'events' member of the zmq_poller_event_t structure.
For standard sockets, this flag is passed through _zmq_poller_wait_all_ to the
underlying _poll()_ system call and generally means that some sort of error
condition is present on the socket specified by 'fd'.
*ZMQ_POLLPRI*::
For 0MQ sockets this flag has no effect on the _zmq_poller_add_ and
_zmq_poller_modify_ functions, and is never set in the
'events' member of the zmq_poller_event_t structure.
For standard sockets this means there
is urgent data to read. Refer to the POLLPRI flag for more informations.
For a file descriptor, refer to your OS documentation: as an example, GPIO
interrupts are signaled through a POLLPRI event.
This flag has no effect on Windows.
NOTE: The _zmq_poller_*_ functions may be implemented or emulated using operating
system interfaces other than _poll()_, and as such may be subject to the limits
of those interfaces in ways not defined in this documentation.
THREAD SAFETY
-------------
Like most other 0MQ objects, a poller is not thread-safe. All operations must
be called from the same thread. Otherwise, behaviour is undefined.
RETURN VALUE
------------
_zmq_poller_new_ always returns a valid pointer to a poller.
All functions that return an int, return -1 in case of a failure. In that case,
zmq_errno() can be used to query the type of the error as described below.
_zmq_poller_wait_all_ returns the number of events signalled and returned in
the events array. It never returns 0.
All other functions return 0 in case of a successful execution.
ERRORS
------
On _zmq_poller_new_:
*ENOMEM*::
A new poller could not be allocated successfully.
On _zmq_poller_destroy_:
*EFAULT*::
_poller_p_ did not point to a valid poller. Note that passing an invalid pointer (e.g.
pointer to deallocated memory) may cause undefined behaviour (e.g. an access violation).
On _zmq_poller_add_, _zmq_poller_modify_ and _zmq_poller_remove_:
*EFAULT*::
_poller_ did not point to a valid poller. Note that passing an
invalid pointer (e.g. pointer to deallocated memory) may cause undefined
behaviour (e.g. an access violation).
*ENOTSOCK*::
_socket_ did not point to a valid socket. Note that passing an
invalid pointer (e.g. pointer to deallocated memory) may cause undefined
behaviour (e.g. an access violation).
On _zmq_poller_add_:
*EMFILE*::
TODO
On _zmq_poller_add_ or _zmq_poller_add_fd_:
*ENOMEM*::
Necessary resources could not be allocated.
*EINVAL*::
_socket_ resp. _fd_ was already registered with the poller.
On _zmq_poller_modify_, _zmq_poller_modify_fd_, _zmq_poller_remove_ or
_zmq_poller_remove_fd_:
*EINVAL*::
_socket_ resp. _fd_ was not registered with the poller.
On _zmq_poller_add_fd_, _zmq_poller_modify_fd_ and _zmq_poller_remove_fd_:
*EBADF**:
The _fd_ specified was the retired fd.
On _zmq_poller_wait_ and _zmq_poller_wait_all_:
*ETERM*::
At least one of the registered objects is a 'socket' whose associated 0MQ
'context' was terminated.
*EFAULT*::
The provided 'events' was NULL, or 'poller' did not point to a valid poller,
or there are no registered objects and 'timeout' was negative.
*EINTR*::
The operation was interrupted by delivery of a signal before any events were
available.
*EAGAIN*::
No registered event was signalled before the timeout was reached.
EXAMPLE
-------
.Polling indefinitely for input events on both a 0MQ socket and a standard socket.
----
void *poller = zmq_poller_new ();
zmq_poller_event_t events [2];
/* First item refers to 0MQ socket 'socket' */
zmq_poller_add (poller, socket, ZMQ_POLLIN, NULL);
/* Second item refers to standard socket 'fd' */
zmq_poller_add_fd (poller, fd, ZMQ_POLLIN, NULL);
/* Poll for events indefinitely */
int rc = zmq_poller_wait_all (items, events, 2, -1);
assert (rc >= 0);
/* Returned events will be stored in 'events' */
zmq_poller_destroy (&poller);
----
SEE ALSO
--------
linkzmq:zmq_socket[3]
linkzmq:zmq_send[3]
linkzmq:zmq_recv[3]
linkzmq:zmq[7]
AUTHORS
-------
This page was written by the 0MQ community. To make a change please
read the 0MQ Contribution Policy at <http://www.zeromq.org/docs:contributing>.

1
doc/zmq_poller_add.txt Symbolic link
View File

@ -0,0 +1 @@
zmq_poller.txt

1
doc/zmq_poller_add_fd.txt Symbolic link
View File

@ -0,0 +1 @@
zmq_poller.txt

1
doc/zmq_poller_destroy.txt Symbolic link
View File

@ -0,0 +1 @@
zmq_poller.txt

1
doc/zmq_poller_modify.txt Symbolic link
View File

@ -0,0 +1 @@
zmq_poller.txt

View File

@ -0,0 +1 @@
zmq_poller.txt

1
doc/zmq_poller_new.txt Symbolic link
View File

@ -0,0 +1 @@
zmq_poller.txt

1
doc/zmq_poller_remove.txt Symbolic link
View File

@ -0,0 +1 @@
zmq_poller.txt

View File

@ -0,0 +1 @@
zmq_poller.txt

1
doc/zmq_poller_wait_all.txt Symbolic link
View File

@ -0,0 +1 @@
zmq_poller.txt

View File

@ -774,7 +774,7 @@ up.
When ZMQ_ROUTER_MANDATORY is set to `1`, 'ZMQ_POLLOUT' events will be generated
if one or more messages can be sent to at least one of the peers. If
ZMQ_ROUTER_MANDATORY is set to `0`, the socket will generate a 'ZMQ_POLLOUT'
event on every call to 'zmq_poll'.
event on every call to 'zmq_poll' resp. 'zmq_poller_wait_all'.
[horizontal]
Option value type:: int

View File

@ -137,7 +137,13 @@ int zmq::socket_poller_t::add (socket_base_t *socket_,
-1
#endif
};
items.push_back (item);
try {
items.push_back (item);
}
catch (const std::bad_alloc &) {
errno = ENOMEM;
return -1;
}
need_rebuild = true;
return 0;
@ -162,7 +168,13 @@ int zmq::socket_poller_t::add_fd (fd_t fd_, void *user_data_, short events_)
-1
#endif
};
items.push_back (item);
try {
items.push_back (item);
}
catch (const std::bad_alloc &) {
errno = ENOMEM;
return -1;
}
need_rebuild = true;
return 0;

View File

@ -1167,7 +1167,9 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_)
void *zmq_poller_new (void)
{
zmq::socket_poller_t *poller = new (std::nothrow) zmq::socket_poller_t;
alloc_assert (poller);
if (!poller) {
errno = ENOMEM;
}
return poller;
}
@ -1295,7 +1297,6 @@ int zmq_poller_remove_fd (void *poller_, int fd_)
return ((zmq::socket_poller_t *) poller_)->remove_fd (fd_);
}
int zmq_poller_wait (void *poller_, zmq_poller_event_t *event_, long timeout_)
{
if (!poller_ || !((zmq::socket_poller_t *) poller_)->check_tag ()) {

View File

@ -339,9 +339,19 @@ void call_poller_modify_unregistered_fails (void *poller, void *socket)
void call_poller_add_no_events (void *poller, void *socket)
{
// add a socket with no events
// TODO should this really be legal? it does not make any sense...
// add a socket with no events initially (may be activated later with
// zmq_poller_modify)
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_add (poller, socket, NULL, 0));
// TODO test that no events are signalled
}
void call_poller_modify_no_events (void *poller, void *socket)
{
// deactivates all events for a socket temporarily (may be activated again
// later with zmq_poller_modify)
zmq_poller_add (poller, socket, NULL, ZMQ_POLLIN);
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_modify (poller, socket, 0));
// TODO test that no events are signalled
}
void call_poller_add_fd_twice_fails (void *poller, void * /*zeromq_socket*/)
@ -389,6 +399,7 @@ TEST_CASE_FUNC_PARAM (call_poller_remove_unregistered_fails,
TEST_CASE_FUNC_PARAM (call_poller_modify_unregistered_fails,
test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_add_no_events, test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_modify_no_events, test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_add_fd_twice_fails, test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_remove_fd_unregistered_fails,
test_with_empty_poller)
@ -603,6 +614,7 @@ int main (void)
RUN_TEST (test_call_poller_remove_unregistered_fails);
RUN_TEST (test_call_poller_modify_unregistered_fails);
RUN_TEST (test_call_poller_add_no_events);
RUN_TEST (test_call_poller_modify_no_events);
RUN_TEST (test_call_poller_add_fd_twice_fails);
RUN_TEST (test_call_poller_remove_fd_unregistered_fails);
RUN_TEST (test_call_poller_modify_fd_unregistered_fails);