zloop(3)
Class for event-driven reactor
Description
ZLOOP
NAME
zloop - Class for event-driven reactor
SYNOPSIS
// This is a
stable class, and may not change except for emergencies. It
// is provided in stable builds.
// Callback function for reactor socket activity
typedef int (zloop_reader_fn) (
zloop_t *loop, zsock_t *reader, void *arg);
// Callback
function for reactor events (low-level)
typedef int (zloop_fn) (
zloop_t *loop, zmq_pollitem_t *item, void *arg);
// Callback for
reactor timer events
typedef int (zloop_timer_fn) (
zloop_t *loop, int timer_id, void *arg);
// Create a new
zloop reactor
CZMQ_EXPORT zloop_t *
zloop_new (void);
// Destroy a
reactor
CZMQ_EXPORT void
zloop_destroy (zloop_t **self_p);
// Register
socket reader with the reactor. When the reader has
messages,
// the reactor will call the handler, passing the arg.
Returns 0 if OK, -1
// if there was an error. If you register the same socket
more than once,
// each instance will invoke its corresponding handler.
CZMQ_EXPORT int
zloop_reader (zloop_t *self, zsock_t *sock, zloop_reader_fn
handler, void *arg);
// Cancel a
socket reader from the reactor. If multiple readers exist
for
// same socket, cancels ALL of them.
CZMQ_EXPORT void
zloop_reader_end (zloop_t *self, zsock_t *sock);
// Configure a
registered reader to ignore errors. If you do not set this,
// then readers that have errors are removed from the
reactor silently.
CZMQ_EXPORT void
zloop_reader_set_tolerant (zloop_t *self, zsock_t
*sock);
// Register
low-level libzmq pollitem with the reactor. When the
pollitem
// is ready, will call the handler, passing the arg. Returns
0 if OK, -1
// if there was an error. If you register the pollitem more
than once, each
// instance will invoke its corresponding handler. A
pollitem with
// socket=NULL and fd=0 means 'poll on FD zero'.
CZMQ_EXPORT int
zloop_poller (zloop_t *self, zmq_pollitem_t *item, zloop_fn
handler, void *arg);
// Cancel a
pollitem from the reactor, specified by socket or FD. If
both
// are specified, uses only socket. If multiple poll items
exist for same
// socket/FD, cancels ALL of them.
CZMQ_EXPORT void
zloop_poller_end (zloop_t *self, zmq_pollitem_t *item);
// Configure a
registered poller to ignore errors. If you do not set this,
// then poller that have errors are removed from the reactor
silently.
CZMQ_EXPORT void
zloop_poller_set_tolerant (zloop_t *self, zmq_pollitem_t
*item);
// Register a
timer that expires after some delay and repeats some number
of
// times. At each expiry, will call the handler, passing the
arg. To run a
// timer forever, use 0 times. Returns a timer_id that is
used to cancel the
// timer in the future. Returns -1 if there was an error.
CZMQ_EXPORT int
zloop_timer (zloop_t *self, size_t delay, size_t times,
zloop_timer_fn handler, void *arg);
// Cancel a
specific timer identified by a specific timer_id (as
returned by
// zloop_timer).
CZMQ_EXPORT int
zloop_timer_end (zloop_t *self, int timer_id);
// Register a
ticket timer. Ticket timers are very fast in the case where
// you use a lot of timers (thousands), and frequently
remove and add them.
// The main use case is expiry timers for servers that
handle many clients,
// and which reset the expiry timer for each message
received from a client.
// Whereas normal timers perform poorly as the number of
clients grows, the
// cost of ticket timers is constant, no matter the number
of clients. You
// must set the ticket delay using zloop_set_ticket_delay
before creating a
// ticket. Returns a handle to the timer that you should use
in
// zloop_ticket_reset and zloop_ticket_delete.
CZMQ_EXPORT void *
zloop_ticket (zloop_t *self, zloop_timer_fn handler, void
*arg);
// Reset a
ticket timer, which moves it to the end of the ticket list
and
// resets its execution time. This is a very fast operation.
CZMQ_EXPORT void
zloop_ticket_reset (zloop_t *self, void *handle);
// Delete a
ticket timer. We do not actually delete the ticket here, as
// other code may still refer to the ticket. We mark as
deleted, and remove
// later and safely.
CZMQ_EXPORT void
zloop_ticket_delete (zloop_t *self, void *handle);
// Set the
ticket delay, which applies to all tickets. If you lower the
// delay and there are already tickets created, the results
are undefined.
CZMQ_EXPORT void
zloop_set_ticket_delay (zloop_t *self, size_t
ticket_delay);
// Set hard
limit on number of timers allowed. Setting more than a small
// number of timers (10-100) can have a dramatic impact on
the performance
// of the reactor. For high-volume cases, use ticket timers.
If the hard
// limit is reached, the reactor stops creating new timers
and logs an
// error.
CZMQ_EXPORT void
zloop_set_max_timers (zloop_t *self, size_t max_timers);
// Set verbose
tracing of reactor on/off. The default verbose setting is
// off (false).
CZMQ_EXPORT void
zloop_set_verbose (zloop_t *self, bool verbose);
// By default
the reactor 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
zloop_set_nonstop (zloop_t *self, bool nonstop);
// Start the
reactor. Takes control of the thread and returns when the
0MQ
// context is terminated or the process is interrupted, or
any event handler
// returns -1. Event handlers may register new sockets and
timers, and
// cancel sockets. Returns 0 if interrupted, -1 if canceled
by a handler.
CZMQ_EXPORT int
zloop_start (zloop_t *self);
// Self test of
this class.
CZMQ_EXPORT void
zloop_test (bool verbose);
Please add '@interface' section in './../src/zloop.c'.
DESCRIPTION
The zloop class provides an event-driven reactor pattern. The reactor handles zmq_pollitem_t items (pollers or writers, sockets or fds), and once-off or repeated timers. Its resolution is 1 msec. It uses a tickless timer to reduce CPU interrupts in inactive processes.
Please add @discuss section in ./../src/zloop.c.
EXAMPLE
From zloop_test method.
// Create two
PAIR sockets and connect over inproc
zsock_t *output = zsock_new (ZMQ_PAIR);
assert (output);
zsock_bind (output, "inproc://zloop.test");
zsock_t *input
= zsock_new (ZMQ_PAIR);
assert (input);
zsock_connect (input, "inproc://zloop.test");
zloop_t *loop =
zloop_new ();
assert (loop);
zloop_set_verbose (loop, verbose);
// Create a
timer that will be cancelled
int timer_id = zloop_timer (loop, 1000, 1, s_timer_event,
NULL);
zloop_timer (loop, 5, 1, s_cancel_timer_event,
&timer_id);
// After 20
msecs, send a ping message to output3
zloop_timer (loop, 20, 1, s_timer_event, output);
// Set up some
tickets that will never expire
zloop_set_ticket_delay (loop, 10000);
void *ticket1 = zloop_ticket (loop, s_timer_event, NULL);
void *ticket2 = zloop_ticket (loop, s_timer_event, NULL);
void *ticket3 = zloop_ticket (loop, s_timer_event,
NULL);
// When we get
the ping message, end the reactor
rc = zloop_reader (loop, input, s_socket_event, NULL);
assert (rc == 0);
zloop_reader_set_tolerant (loop, input);
zloop_start (loop);
zloop_ticket_delete
(loop, ticket1);
zloop_ticket_delete (loop, ticket2);
zloop_ticket_delete (loop, ticket3);
// Check
whether loop properly ignores zsys_interrupted flag
// when asked to
zloop_destroy (&loop);
loop = zloop_new ();
bool
timer_event_called = false;
zloop_timer (loop, 1, 1, s_timer_event3,
&timer_event_called);
zsys_interrupted
= 1;
zloop_start (loop);
// zloop returns immediately without giving any handler a
chance to run
assert (!timer_event_called);
zloop_set_nonstop
(loop, true);
zloop_start (loop);
// zloop runs the handler which will terminate the loop
assert (timer_event_called);
zsys_interrupted = 0;
// Check if
reader removed in timer is not called
zloop_destroy (&loop);
loop = zloop_new ();
bool
socket_event_called = false;
zloop_reader (loop, output, s_socket_event1,
&socket_event_called);
zloop_timer (loop, 0, 1, s_timer_event5, output);
zstr_send (input, "PING");
zloop_start
(loop);
assert (!socket_event_called);
// cleanup
zloop_destroy (&loop);
assert (loop == NULL);
zsock_destroy
(&input);
zsock_destroy (&output);
#if defined
(__WINDOWS__)
zsys_shutdown();
#endif
AUTHORS
The czmq manual was written by the authors in the AUTHORS file.
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
|
1. |
zeromq-dev@lists.zeromq.org |
mailto:zeromq-dev@lists.zeromq.org