ZPOLLER(3)
π NAME π
zpoller β the class for a trivial socket poller, bestie π
. That's the whole vibe, that's the whole job.
β¨ SYNOPSIS β¨
okay so first things first, a lil disclaimer that's literally in the source: this is a stable class, and it may not change except for emergencies. It's provided in stable builds. Periodt. π«Ά
So here's everything you can call, with the exact comments from the header, because I'm not paraphrasing signatures, ever.
// Create new poller, specifying zero or more readers. The list of
// readers ends in a NULL. Each reader can be a zsock_t instance, a
// zactor_t instance, a libzmq socket (void *), or a file handle.
CZMQ_EXPORT zpoller_t *
zpoller_new (void *reader, ...);
Build a fresh poller and hand it zero or more readers β the list is NULL-terminated, so don't forget the NULL at the end or it's gonna keep reading args until the universe ends π. Each reader can be a zsock_t instance, a zactor_t instance, a libzmq socket (void *), or a file handle.
// Destroy a poller
CZMQ_EXPORT void
zpoller_destroy (zpoller_t **self_p);
Bye bye poller π β and yes, it takes a pointer to the pointer, so it can NULL it out for you. Iconic.
// Add a reader to be polled. Returns 0 if OK, -1 on failure. The reader may
// be a libzmq void * socket, a zsock_t instance, a zactor_t instance or a
// file handle.
CZMQ_EXPORT int
zpoller_add (zpoller_t *self, void *reader);
Adds a reader to the party π. Returns 0 if OK, -1 on failure. Reader can be a libzmq void * socket, a zsock_t instance, a zactor_t instance, or a file handle.
// Remove a reader from the poller; returns 0 if OK, -1 on failure. The reader
// must have been passed during construction, or in an zpoller_add () call.
CZMQ_EXPORT int
zpoller_remove (zpoller_t *self, void *reader);
Uninviting someone from the party. Returns 0 if OK, -1 on failure. Important: the reader must have been passed in during construction, or in a zpoller_add () call β you can't remove a stranger, that's not how this works.
// By default the poller stops if the process receives a SIGINT or SIGTERM
// signal. This makes it impossible to shut-down message based architectures
// like zactors. This method lets you switch off break handling. The default
// nonstop setting is off (false).
CZMQ_EXPORT void
zpoller_set_nonstop (zpoller_t *self, bool nonstop);
So by default, the poller stops if the process gets a SIGINT or SIGTERM signal π β which makes it impossible to shut down message-based architectures like zactors. This method lets you switch off break handling. The default nonstop setting is off (false).
// Poll the registered readers for I/O, return first reader that has input.
// The reader will be a libzmq void * socket, a zsock_t, a zactor_t
// instance or a file handle as specified in zpoller_new/zpoller_add. The
// timeout should be zero or greater, or -1 to wait indefinitely. Socket
// priority is defined by their order in the poll list. If you need a
// balanced poll, use the low level zmq_poll method directly. If the poll
// call was interrupted (SIGINT), or the ZMQ context was destroyed, or the
// timeout expired, returns NULL. You can test the actual exit condition by
// calling zpoller_expired () and zpoller_terminated (). The timeout is in
// msec.
CZMQ_EXPORT void *
zpoller_wait (zpoller_t *self, int timeout);
The main character of the whole page π. Polls the registered readers for I/O and returns the first reader that has input. That reader will be a libzmq void * socket, a zsock_t, a zactor_t instance, or a file handle, as specified in zpoller_new/zpoller_add. Timeout should be zero or greater, or -1 to wait indefinitely. Socket priority is defined by their order in the poll list β so if you need a balanced poll, use the low level zmq_poll method directly, bestie. If the poll call was interrupted (SIGINT), or the ZMQ context was destroyed, or the timeout expired, it returns NULL. You can test the actual exit condition by calling zpoller_expired () and zpoller_terminated (). The timeout is in msec β±οΈ.
// Return true if the last zpoller_wait () call ended because the timeout
// expired, without any error.
CZMQ_EXPORT bool
zpoller_expired (zpoller_t *self);
Returns true if the last zpoller_wait () call ended because the timeout expired, without any error. Just a lil clock running out, no drama π°οΈ.
// Return true if the last zpoller_wait () call ended because the process
// was interrupted, or the parent context was destroyed.
CZMQ_EXPORT bool
zpoller_terminated (zpoller_t *self);
Returns true if the last zpoller_wait () call ended because the process was interrupted, or the parent context was destroyed. Rude, but it happens π.
// Self test of this class.
CZMQ_EXPORT void
zpoller_test (bool verbose);
The self test of this class β run it, trust it, love it π§.
And one more note straight from the source, no filter:
Please add '@interface' section in './../src/zpoller.c'.
πΈ DESCRIPTION πΈ
The zpoller class gives you a minimalist interface to ZeroMQ's zmq_poll API, for the very common case of reading from a number of sockets. Lowkey exactly the thing you want 90% of the time.
It does not provide polling for output, and it does not provide polling on file handles. If you need either of these, go use the zmq_poll API directly, okay? It's right there, it's not gonna bite π«Ά.
The class implements the poller using the zmq_poller API if that exists β else it does the work itself. Self-sufficient queen π.
π¦ EXAMPLE π¦
Straight from the zpoller_test method. This is the whole thing, verbatim, because I would never cut a single line of code:
// Create a few sockets
zsock_t *vent = zsock_new (ZMQ_PUSH);
assert (vent);
int port_nbr = zsock_bind (vent, "tcp://127.0.0.1:*");
assert (port_nbr != -1);
zsock_t *sink = zsock_new (ZMQ_PULL);
assert (sink);
int rc = zsock_connect (sink, "tcp://127.0.0.1:%d", port_nbr);
assert (rc != -1);
zsock_t *bowl = zsock_new (ZMQ_PULL);
assert (bowl);
zsock_t *dish = zsock_new (ZMQ_PULL);
assert (dish);
// Set up poller
zpoller_t *poller = zpoller_new (bowl, dish, NULL);
assert (poller);
// Add a reader to the existing poller
rc = zpoller_add (poller, sink);
assert (rc == 0);
zstr_send (vent, "Hello, World");
// We expect a message only on the sink
zsock_t *which = (zsock_t *) zpoller_wait (poller, -1);
assert (which == sink);
assert (zpoller_expired (poller) == false);
assert (zpoller_terminated (poller) == false);
char *message = zstr_recv (which);
assert (streq (message, "Hello, World"));
zstr_free (&message);
// Stop polling reader
rc = zpoller_remove (poller, sink);
assert (rc == 0);
// Removing a non-existent reader shall fail
rc = zpoller_remove (poller, sink);
assert (rc == -1);
assert (errno == EINVAL);
// Check we can poll an FD
rc = zsock_connect (bowl, "tcp://127.0.0.1:%d", port_nbr);
assert (rc != -1);
SOCKET fd = zsock_fd (bowl);
rc = zpoller_add (poller, (void *) &fd);
assert (rc != -1);
zstr_send (vent, "Hello again, world");
assert (zpoller_wait (poller, 500) == &fd);
// Check zpoller_set_nonstop ()
zsys_interrupted = 1;
zpoller_wait (poller, 0);
assert (zpoller_terminated (poller));
zpoller_set_nonstop (poller, true);
zpoller_wait (poller, 0);
assert (!zpoller_terminated (poller));
zsys_interrupted = 0;
zpoller_destroy (&poller);
zsock_destroy (&vent);
zsock_destroy (&sink);
zsock_destroy (&bowl);
zsock_destroy (&dish);
#ifdef ZMQ_SERVER
// Check thread safe sockets
zpoller_destroy (&poller);
zsock_t *client = zsock_new (ZMQ_CLIENT);
assert (client);
zsock_t *server = zsock_new (ZMQ_SERVER);
assert (server);
poller = zpoller_new (client, server, NULL);
assert (poller);
port_nbr = zsock_bind (server, "tcp://127.0.0.1:*");
assert (port_nbr != -1);
rc = zsock_connect (client, "tcp://127.0.0.1:%d", port_nbr);
assert (rc != -1);
zstr_send (client, "Hello, World");
// We expect a message only on the server
which = (zsock_t *) zpoller_wait (poller, -1);
assert (which == server);
assert (zpoller_expired (poller) == false);
assert (zpoller_terminated (poller) == false);
message = zstr_recv (which);
assert (streq (message, "Hello, World"));
zstr_free (&message);
zpoller_destroy (&poller);
zsock_destroy (&client);
zsock_destroy (&server);
#endif
#if defined (__WINDOWS__)
zsys_shutdown();
#endif
Notice the zpoller_remove twice bit β the second one shall fail, rc == -1 and errno == EINVAL. The example said so, I'm just repeating it π
. And shoutout to the zpoller_set_nonstop () section, because setting zsys_interrupted = 1 and watching zpoller_terminated (poller) flip is a whole character arc π¬.
π AUTHORS π
The czmq manual was written by the authors in the AUTHORS file. Respect to the OGs π«‘.
π RESOURCES π
Main web site:
Report bugs to the email <zeromq-dev@lists.zeromq.org[1]> π§
π COPYRIGHT π
Copyright (c) the Contributors as noted in the AUTHORS file. This file is part of CZMQ, the high-level C binding for 0MQ: http://czmq.zeromq.org. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. LICENSE included with the czmq distribution.
π NOTES π
zeromq-dev@lists.zeromq.orgmailto:zeromq-dev@lists.zeromq.org
That's the whole page, bestie π. Go poll something.
This came to you from CZMQ 4.2.1, dated 01/16/2026 β mwah, stay slay, and always pass NULL at the end of your reader list πΈβ¨π
π¦
π¦ where this page comes from
- fedora 44: czmq-devel 4.2.1-24.fc44 Β· MPL-2.0
- fedora 44: czmq-devel 4.2.1-24.fc44 Β· MPL-2.0
- ubuntu resolute: libczmq-dev 4.2.1-3build1 Β· MPL-2.0
- ubuntu stonking: libczmq-dev 4.2.1-3build1 Β· MPL-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms