1/*
2 Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
3
4 This file is part of libzmq, the ZeroMQ core engine in C++.
5
6 libzmq is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License (LGPL) as published
8 by the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 As a special exception, the Contributors give you permission to link
12 this library with independent modules to produce an executable,
13 regardless of the license terms of these independent modules, and to
14 copy and distribute the resulting executable under terms of your choice,
15 provided that you also meet, for each linked independent module, the
16 terms and conditions of the license of that module. An independent
17 module is a module which is not derived from or based on this library.
18 If you modify this library, you must extend this exception to your
19 version of the library.
20
21 libzmq is distributed in the hope that it will be useful, but WITHOUT
22 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24 License for more details.
25
26 You should have received a copy of the GNU Lesser General Public License
27 along with this program. If not, see <http://www.gnu.org/licenses/>.
28*/
29
30#ifndef __ZMQ_POLLER_BASE_HPP_INCLUDED__
31#define __ZMQ_POLLER_BASE_HPP_INCLUDED__
32
33#include <map>
34
35#include "clock.hpp"
36#include "atomic_counter.hpp"
37#include "ctx.hpp"
38
39namespace zmq
40{
41struct i_poll_events;
42
43// A build of libzmq must provide an implementation of the poller_t concept. By
44// convention, this is done via a typedef.
45//
46// At the time of writing, the following implementations of the poller_t
47// concept exist: zmq::devpoll_t, zmq::epoll_t, zmq::kqueue_t, zmq::poll_t,
48// zmq::pollset_t, zmq::select_t
49//
50// An implementation of the poller_t concept must provide the following public
51// methods:
52// Returns load of the poller.
53// int get_load() const;
54//
55// Add a timeout to expire in timeout_ milliseconds. After the
56// expiration, timer_event on sink_ object will be called with
57// argument set to id_.
58// void add_timer(int timeout_, zmq::i_poll_events *sink_, int id_);
59//
60// Cancel the timer created by sink_ object with ID equal to id_.
61// void cancel_timer(zmq::i_poll_events *sink_, int id_);
62//
63// Adds a fd to the poller. Initially, no events are activated. These must
64// be activated by the set_* methods using the returned handle_.
65// handle_t add_fd(fd_t fd_, zmq::i_poll_events *events_);
66//
67// Deactivates any events that may be active for the given handle_, and
68// removes the fd associated with the given handle_.
69// void rm_fd(handle_t handle_);
70//
71// The set_* and reset_* methods activate resp. deactivate polling for
72// input/output readiness on the respective handle_, such that the
73// in_event/out_event methods on the associated zmq::i_poll_events object
74// will be called.
75// Note: while handle_t and fd_t may be the same type, and may even have the
76// same values for some implementation, this may not be assumed in general.
77// The methods may only be called with the handle returned by add_fd.
78// void set_pollin(handle_t handle_);
79// void reset_pollin(handle_t handle_);
80// void set_pollout(handle_t handle_);//
81// void reset_pollout(handle_t handle_);
82//
83// Starts operation of the poller. See below for details.
84// void start();
85//
86// Request termination of the poller.
87// TODO: might be removed in the future, as it has no effect.
88// void stop();
89//
90// Returns the maximum number of fds that can be added to an instance of the
91// poller at the same time, or -1 if there is no such fixed limit.
92// static int max_fds();
93//
94// Most of the methods may only be called from a zmq::i_poll_events callback
95// function when invoked by the poller (and, therefore, typically from the
96// poller's worker thread), with the following exceptions:
97// - get_load may be called from outside
98// - add_fd and add_timer may be called from outside before start
99// - start may be called from outside once
100//
101// After a poller is started, it waits for the registered events (input/output
102// readiness, timeout) to happen, and calls the respective functions on the
103// zmq::i_poll_events object. It terminates when no further registrations (fds
104// or timers) exist.
105//
106// Before start, add_fd must have been called at least once. Behavior may be
107// undefined otherwise.
108//
109// If the poller is implemented by a single worker thread (the
110// worker_poller_base_t base class may be used to implement such a poller),
111// no synchronization is required for the data structures modified by
112// add_fd, rm_fd, add_timer, cancel_timer, (re)set_poll(in|out). However,
113// reentrancy must be considered, e.g. when one of the functions modifies
114// a container that is being iterated by the poller.
115
116
117// A class that can be used as a base class for implementations of the poller
118// concept.
119//
120// For documentation of the public methods, see the description of the poller_t
121// concept.
122class poller_base_t
123{
124 public:
125 poller_base_t ();
126 virtual ~poller_base_t ();
127
128 // Methods from the poller concept.
129 int get_load () const;
130 void add_timer (int timeout_, zmq::i_poll_events *sink_, int id_);
131 void cancel_timer (zmq::i_poll_events *sink_, int id_);
132
133 protected:
134 // Called by individual poller implementations to manage the load.
135 void adjust_load (int amount_);
136
137 // Executes any timers that are due. Returns number of milliseconds
138 // to wait to match the next timer or 0 meaning "no timers".
139 uint64_t execute_timers ();
140
141 private:
142 // Clock instance private to this I/O thread.
143 clock_t _clock;
144
145 // List of active timers.
146 struct timer_info_t
147 {
148 zmq::i_poll_events *sink;
149 int id;
150 };
151 typedef std::multimap<uint64_t, timer_info_t> timers_t;
152 timers_t _timers;
153
154 // Load of the poller. Currently the number of file descriptors
155 // registered.
156 atomic_counter_t _load;
157
158 ZMQ_NON_COPYABLE_NOR_MOVABLE (poller_base_t)
159};
160
161// Base class for a poller with a single worker thread.
162class worker_poller_base_t : public poller_base_t
163{
164 public:
165 worker_poller_base_t (const thread_ctx_t &ctx_);
166
167 // Methods from the poller concept.
168 void start (const char *name = NULL);
169
170 protected:
171 // Checks whether the currently executing thread is the worker thread
172 // via an assertion.
173 // Should be called by the add_fd, removed_fd, set_*, reset_* functions
174 // to ensure correct usage.
175 void check_thread ();
176
177 // Stops the worker thread. Should be called from the destructor of the
178 // leaf class.
179 void stop_worker ();
180
181 private:
182 // Main worker thread routine.
183 static void worker_routine (void *arg_);
184
185 virtual void loop () = 0;
186
187 // Reference to ZMQ context.
188 const thread_ctx_t &_ctx;
189
190 // Handle of the physical thread doing the I/O work.
191 thread_t _worker;
192};
193}
194
195#endif
196