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_SELECT_HPP_INCLUDED__ |
31 | #define __ZMQ_SELECT_HPP_INCLUDED__ |
32 | |
33 | // poller.hpp decides which polling mechanism to use. |
34 | #include "poller.hpp" |
35 | #if defined ZMQ_IOTHREAD_POLLER_USE_SELECT |
36 | |
37 | #include <stddef.h> |
38 | #include <vector> |
39 | #include <map> |
40 | |
41 | #if defined ZMQ_HAVE_WINDOWS |
42 | #elif defined ZMQ_HAVE_OPENVMS |
43 | #include <sys/types.h> |
44 | #include <sys/time.h> |
45 | #else |
46 | #include <sys/select.h> |
47 | #endif |
48 | |
49 | #include "ctx.hpp" |
50 | #include "fd.hpp" |
51 | #include "poller_base.hpp" |
52 | |
53 | namespace zmq |
54 | { |
55 | struct i_poll_events; |
56 | |
57 | // Implements socket polling mechanism using POSIX.1-2001 select() |
58 | // function. |
59 | |
60 | class select_t : public worker_poller_base_t |
61 | { |
62 | public: |
63 | typedef fd_t handle_t; |
64 | |
65 | select_t (const thread_ctx_t &ctx_); |
66 | ~select_t (); |
67 | |
68 | // "poller" concept. |
69 | handle_t add_fd (fd_t fd_, zmq::i_poll_events *events_); |
70 | void rm_fd (handle_t handle_); |
71 | void set_pollin (handle_t handle_); |
72 | void reset_pollin (handle_t handle_); |
73 | void set_pollout (handle_t handle_); |
74 | void reset_pollout (handle_t handle_); |
75 | void stop (); |
76 | |
77 | static int max_fds (); |
78 | |
79 | private: |
80 | // Main event loop. |
81 | void loop (); |
82 | |
83 | // Internal state. |
84 | struct fds_set_t |
85 | { |
86 | fds_set_t (); |
87 | fds_set_t (const fds_set_t &other_); |
88 | fds_set_t &operator= (const fds_set_t &other_); |
89 | // Convenience method to descriptor from all sets. |
90 | void remove_fd (const fd_t &fd_); |
91 | |
92 | fd_set read; |
93 | fd_set write; |
94 | fd_set error; |
95 | }; |
96 | |
97 | struct fd_entry_t |
98 | { |
99 | fd_t fd; |
100 | zmq::i_poll_events *events; |
101 | }; |
102 | typedef std::vector<fd_entry_t> fd_entries_t; |
103 | |
104 | void trigger_events (const fd_entries_t &fd_entries_, |
105 | const fds_set_t &local_fds_set_, |
106 | int event_count_); |
107 | |
108 | struct family_entry_t |
109 | { |
110 | family_entry_t (); |
111 | |
112 | fd_entries_t fd_entries; |
113 | fds_set_t fds_set; |
114 | bool has_retired; |
115 | }; |
116 | |
117 | void select_family_entry (family_entry_t &family_entry_, |
118 | int max_fd_, |
119 | bool use_timeout_, |
120 | struct timeval &tv_); |
121 | |
122 | #if defined ZMQ_HAVE_WINDOWS |
123 | typedef std::map<u_short, family_entry_t> family_entries_t; |
124 | |
125 | struct wsa_events_t |
126 | { |
127 | wsa_events_t (); |
128 | ~wsa_events_t (); |
129 | |
130 | // read, write, error and readwrite |
131 | WSAEVENT events[4]; |
132 | }; |
133 | |
134 | family_entries_t _family_entries; |
135 | // See loop for details. |
136 | family_entries_t::iterator _current_family_entry_it; |
137 | |
138 | int try_retire_fd_entry (family_entries_t::iterator family_entry_it_, |
139 | zmq::fd_t &handle_); |
140 | |
141 | static const size_t fd_family_cache_size = 8; |
142 | std::pair<fd_t, u_short> _fd_family_cache[fd_family_cache_size]; |
143 | |
144 | u_short get_fd_family (fd_t fd_); |
145 | |
146 | // Socket's family or AF_UNSPEC on error. |
147 | static u_short determine_fd_family (fd_t fd_); |
148 | #else |
149 | // on non-Windows, we can treat all fds as one family |
150 | family_entry_t _family_entry; |
151 | fd_t _max_fd; |
152 | #endif |
153 | |
154 | void cleanup_retired (); |
155 | bool cleanup_retired (family_entry_t &family_entry_); |
156 | |
157 | // Checks if an fd_entry_t is retired. |
158 | static bool is_retired_fd (const fd_entry_t &entry_); |
159 | |
160 | static fd_entries_t::iterator |
161 | find_fd_entry_by_handle (fd_entries_t &fd_entries_, handle_t handle_); |
162 | |
163 | ZMQ_NON_COPYABLE_NOR_MOVABLE (select_t) |
164 | }; |
165 | |
166 | typedef select_t poller_t; |
167 | } |
168 | |
169 | #endif |
170 | |
171 | #endif |
172 | |