Flow 3.0.0
Flow project: Full implementation reference.
event_set.hpp
Go to the documentation of this file.
1/* Flow
2 * Copyright 2023 Akamai Technologies, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the
5 * "License"); you may not use this file except in
6 * compliance with the License. You may obtain a copy
7 * of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in
12 * writing, software distributed under the License is
13 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
14 * CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing
16 * permissions and limitations under the License. */
17
18/// @file
19#pragma once
20
23#include "flow/util/traits.hpp"
25#include <boost/shared_ptr.hpp>
26#include <boost/enable_shared_from_this.hpp>
27#include <boost/any.hpp>
28#include <boost/unordered/unordered_map.hpp>
29
30namespace flow::net_flow
31{
32// Types.
33
34/**
35 * A user-set collection of sockets and desired conditions on those sockets (such as: "socket has data
36 * to read"), with the ability to wait for those conditions to become true and signal the user when so.
37 *
38 * @note Important: With the somewhat more recent availability of the asio::Node hierarchy, which slickly adds
39 * boost.asio-event-loop-integration to the Node hierarchy, public use of this class Event_set should be avoided
40 * for those already using a boost.asio event loop. It is both significantly simpler -- and a bit faster --
41 * to use Peer_socket::async_send(), Server_socket::async_accept(), etc. -- as well as a bit faster.
42 * IN PARTICULAR, the complex discussion in Event_set doc header regarding async_wait() with a glue socket
43 * is something one should skip over if one could just integrate directly into a boost.asio loop.
44 * @note Advice: Even if you don't already use a boost.asio event loop, consider doing so before giving up and going for
45 * an Event_set glue pattern as described in this class doc header. Your application may be sigificantly simpler
46 * and more maintainable as a result.
47 * @note Advice: In general, please read the bird's eye view of the entire set of I/O ops in `net_flow`; this is found
48 * in asio::Node doc header. This should help hugely in choosing the right type of operating mode in the context
49 * of a non-trivial application, possibly featuring other types of I/O in addition to the Flow protocol.
50 * @note All that said, Event_set is a very important facility and is, at the very least, built-upon internally for all
51 * but the basic non-blocking ops. Advanced users should understand it (even if they don't use it directly).
52 *
53 * This fulfills the same role as BSD sockets' `select()` (and its more powerful non-portable
54 * equivalents like epoll, kqueue, etc.). In addition to the feature set provided by functions such
55 * as `select()`, Event_set provides a way to work together with the OS's built-in `select()`
56 * equivalent; that is to say it provides a way to add Flow-protocol sockets into an event loop written in
57 * terms of `select()` or spritiually similar facilities (epoll, kqueue, etc.).
58 *
59 * The simplest way to use Event_set is to not use it directly at all. Instead, use the blocking
60 * methods such as Peer_socket::sync_receive(), Peer_socket::sync_send(), Node::sync_connect(), and
61 * Server_socket::sync_accept(). Such methods will internally construct an Event_set with the
62 * target socket and perform work (namely some Event_set::sync_wait() calls) on it, hidden from the caller.
63 * This mode of operation is analogous to BSD sockets' blocking functions (e.g., `recv()` in blocking
64 * mode -- POSIX `O_NONBLOCK` bit set / WinSock `FIONBIO` mode is enabled).
65 *
66 * This is often insufficient, as in event loops of any complexity. The next simplest way to use
67 * Event_set is to use a synchronous wait. To do so, construct an Event_set, add the desired
68 * <em>(socket, desired event on that socket)</em> pairs to it (see the swap_wanted_sockets(), add_wanted_socket(),
69 * remove_wanted_socket() methods), then perform sync_wait() (with an optional timeout). Once that method
70 * returns (which happens once either 1 or more events are active, there is a timeout, or wait is
71 * interrupted via Node::interrupt_all_waits()), examine which events (if any) were found to be active, then perform
72 * the appropriate operation (e.g., `serv->accept()` if Acceptable, `sock->send()` if Writable) on each active
73 * socket/event pair. This mode of operation is analogous to `FD_SET(); select(); FD_ISSET()` or
74 * `epoll_ctl(); epoll_wait()`. The key feature is that the sync_wait() (like `select()` or `epoll_wait()`) call blocks
75 * the calling thread until there are events or a timeout or a global interrupt (the latter similar to POSIX `EINTR`
76 * caused by a signal). Additionally, the Event_set::poll() method is analogous to a `select()` call with a 0 timeout.
77 *
78 * The above is sufficient when writing an event loop that works *only* with Flow-protocol sockets. However,
79 * many practical applications will use an event loop that works with Flow-protocol sockets and other
80 * resources (e.g., TCP sockets, pipes) simultaneously. Then what?
81 * - If you have a boost.asio event loop, then (again) the best way to use Event_set is by not using it directly;
82 * instead use asio::Node hierarchy to use Flow-protocol sockets as 1st-class-citizen boost.asio-style I/O objects.
83 * Internally, again, an Event_set will be indirectly used; but one would not use it directly.
84 * - Otherwise -- if there is no boost.asio event loop, and it's impractical to convert to using one (generally a
85 * a good idea but may not be practical under time constraints), then direct use the core Event_set feature
86 * (namely Event_set::async_wait()) is just the ticket.
87 *
88 * We now discuss Event_set::async_wait(). The basic deficiency of sync_wait() is simply that it will only wake up
89 * if there's a Flow-protocol event and knows nothing about anything
90 * else. Similarly, your `select()`-or-equivalent-of-choice
91 * will know nothing of Flow-protocol events, since it can only work with standard file descriptors
92 * (or whatever), not Flow sockets. For this case Event_set provides asynchronous waiting. As
93 * before, you'll construct an Event_set and add some desired sockets/events. Then, call
94 * `async_wait(F)`, where `F()` is a function. async_wait() will IMMEDIATELY return. However, another,
95 * unspecified, thread will wait for the desired condition(s) to become true. Once that occurs,
96 * that unspecified thread will call `F()`. `F()` can do whatever you want (but see restrictions
97 * documented on async_wait()); however in the use case described in this paragraph it will probably
98 * want to do something that will wake up the `select()` (or `epoll_wait()`, or ...) of your main event
99 * loop. For example, you can set up a Unix domain socket or pipe and add it into your `select()` (or
100 * equivalent's) event set; and then have `F()` write 1 byte to it. Once this occurs, that `select()`
101 * (etc.) will wake up; you can call `async_wait_finish()` and then check the active Flow-protocol events using
102 * the same techniques as shown in the preceding paragraph, after having called sync_wait().
103 *
104 * The following illustrates the preceding paragraph. In this example, we are interested in a single TCP
105 * socket from which to read; and a single Flow socket from which to read. This can be extended to more
106 * native and Flow socket types, more sockets, and more sophisticated native mechanisms than `select()`;
107 * but basically this is it. (However, in case of `select()` and its peculiar `FD_SET()` semantics, please
108 * note that this examples combines `sel_read_set` to handle both the special local "linking" socket `comm_sock`
109 * and the TCP-readable socket `tcp_sock`. If you want to check for another type of event than being "readable" --
110 * e.g., "writable" -- then with `select()` you'd need to make a separate event set, perhaps named `sel_write_set`,
111 * and it would not be handling `comm_sock`, in whose case we only care about readability. Note also that
112 * the example event loop iteration shown below models situation where `tcp_sock` and `flow_sock` happen to
113 * both become readable just about at the same time, causing `select()` to return with 2 sockets in readable state
114 * simultaneously for illustration purposes. Realistically probably one would become readable; then in another
115 * loop iteration the other would... but this would be annoyingly lengthy to show; and though this is less
116 * probable, it's still possible.
117 *
118 * ~~~
119 * // NOTE: ASCII art arrows |--------> (etc.) indicate thread execution. "U" is the user thread.
120 * // "K" is unspecified kernel "thread." "W" is unspecified `net_flow` working thread.
121 * // T (cont.) just means thread T was already running up to the point we are illustrating.
122 *
123 * U (cont.)
124 * | Set up local socket (e.g., Unix domain socket or localhost TCP socket) comm_sock.
125 * | Set up select() native socket set sel_read_set, for native "readable" events.
126 * | Set up net_flow::Event_set flow_set.
127 * | FD_SET(comm_sock, sel_read_set);
128 * | Set up native TCP peer socket tcp_sock.
129 * | Set up Flow peer socket flow_sock.
130 * | FD_SET(tcp_sock, sel_read_set);
131 * | flow_set.add_wanted_socket(flow_sock, Event_type::S_PEER_SOCKET_READABLE);
132 * | Event loop begins here. <--------------------------------------+ K (cont.) W (cont.)
133 * | flow_set.async_wait(handle_flow_ev); | | ... | ...
134 * | Inform W. -> | | ... | flow_set -> WAITING.
135 * | select(2, sel_read_set, NULL, NULL, ...positive-timeout...); | | ... | ...
136 * | ...select() blocking... | | ... | ...
137 * | ... | | ... | ...
138 * | ... | | tcp_sock readable! | ...
139 * | ... | | <- Tell select(). |
140 * | K says tcp_sock readable! Get ready to return! | | ... | flow_sock readable!
141 * | | | | handle_flow_ev():
142 * | | | | Write 1 -> comm_sock.
143 * | | | comm_sock readable! |
144 * | | | <- Tell select(). |
145 * | K says comm_sock readable, and that's it. Return! | | ... | ...
146 * | flow_set.async_wait_finish(); | v | ...
147 * | Inform W. -> | | ...
148 * | if (FD_ISSET(tcp_sock, sel_read_set)) | | flow_set -> INACTIVE.
149 * | Non-blocking recv(tcp_sock) until exhausted! | v
150 * | if (FD_ISSET(comm_sock, sel_read_set)) |
151 * | In this example we've only 1 Flow socket and event, so: \ |
152 * | flow_sock.async_receive() until exhausted! |
153 * | Event loop ends here. -----------------------------------------+
154 * v
155 * ~~~
156 *
157 * The above are informal suggestions for use. Here is the more formal description of operation of
158 * an Event_set. Event_set is a simple state machine with three states: INACTIVE, WAITING, CLOSED.
159 * After construction (which is done by Node in a factory fashion), Event_set is in INACTIVE state.
160 * CLOSED means the Event_set has been Event_set::close()d, or the originating Node has been destroyed. It is
161 * not possible to perform any operations on a CLOSED Event_set, nor is it possible to exit the CLOSED
162 * state. A CLOSED Event_set stores no resources and will be deleted via `shared_ptr<>` mechanics
163 * once all user references to it are gone.
164 *
165 * The rest of the time, Event_set switches back and forth between INACTIVE and WAITING. In
166 * INACTIVE, you may set and examine the desired sockets/events. The following are supported (see also
167 * Event_set::Event_type `enum` values)
168 *
169 * - <em>Peer_socket Readable</em>: true if and only if `sock->receive()` with unlimited target buffer
170 * space would return either a non-zero number of bytes or indicate an error. (Therefore "not Readable"
171 * means it would return 0 but no error.)
172 * - <em>Peer_socket Writable</em>: same but with `sock->send()`. Note, however, that typically this is
173 * more likely to be immediately true on a given socket; if there's space in the Send buffer for a certain
174 * small amount of data, then the socket owning it is Writable; whereas data have to actually have arrived
175 * from the other side for it to be Readable. Nevertheless, if network conditions are such that the
176 * Send buffer cannot be purged via sending its contents to the other side, then eventually it won't be
177 * Writable either (so don't count on writability without checking).
178 * - <em>Server_socket Acceptable</em>: true if and only if `serv->accept()` would return either a non-null
179 * Server_socket::Ptr or indicate an error. (Therefore "not Acceptable" means it would return
180 * null but no error.)
181 *
182 * The desired events can be specified with swap_wanted_sockets(), add_wanted_socket(),
183 * and remove_wanted_socket(). Note that all of these methods are efficient (no copying
184 * of socket sets involved). Also note that all the socket objects passed to an Event_set must come
185 * from the same Node as that Event_set; else behavior is undefined.
186 *
187 * Also in INACTIVE, you may examine the results of the last wait, if any. Do this using
188 * emit_result_sockets(), etc. Note that these methods are also efficient (no copying) and can
189 * only be used once for each wait (all subsequent uses yield empty socket sets).
190 *
191 * In WAITING state, a wait for the specified events has started. async_wait(), sync_wait(), and
192 * poll() change state from INACTIVE to WAITING. In WAITING state, all of the above methods return
193 * errors. The following pieces of code change state back to INACTIVE: async_wait_finish(),
194 * sync_wait() (once an event is true, or timeout), poll() (immediately), and an unspecified
195 * non-user thread if async_wait() was used, and an event has been asynchronously detected.
196 *
197 * In particular, if `Event_set e` is used by 1 thread, and that thread performs only sync_wait()s for
198 * waiting, user code will never be able to observe the WAITING state, as sync_wait() will go
199 * INACTIVE->WAITING->INACTIVE internally.
200 *
201 * ### Relationship between 2 different Event_set objects ###
202 * They are entirely independent. In particular, you
203 * may put the same socket+event combo into 2 different Event_set objects and wait on both Event_sets
204 * simultaneously. If that socket/event holds for both Event_set objects at the same time, both will
205 * be signalled. I informally recommend against using this. For example, if the event is "sock is
206 * Readable," and you will `receive()` as a result, which of the two `receive()` calls gets what data?
207 * However there may be a reasonable use case for the Acceptable event.
208 *
209 * ### Signals and interruption ###
210 * Any POSIX blocking function, once it has started waiting, will exit with `errno == EINTR`
211 * if a signal is delivered. (Sometimes this is just annoying, but sometimes it's useful: if SIGTERM
212 * handler sets some global terminate flag, then the signal delivery will immediately break out of
213 * the blocking call, so the flag can be immediately checked by the main code (and then the program
214 * can cleanly exit, for example).) Event_set::sync_wait() and Event_set::async_wait() support
215 * similar functionality. Call Node::interrupt_all_waits() to interrupt any Event_set object(s) within
216 * that Node currently in WAITING state. They enter INACTIVE state, and it is indicated to the
217 * user of each sync_wait() or async_wait() that the reason for the wait's finish was an interruption
218 * (see those functions for details on how this is communicated). Conceptually this is similar to
219 * POSIX blocking `select()` or blocking `recv()` returning -1/`EINTR`.
220 *
221 * To actually cause signals to trigger Node::interrupt_all_waits() (as occurs by default,
222 * conceptually, in POSIX programs w/r/t `EINTR`), the user has two basic options. They can either
223 * register signal handlers that'll explicitly invoke that method; or they can let Node do so
224 * automatically for SIGINT and SIGTERM. This is controlled by the Node option
225 * Node_options::m_st_capture_interrupt_signals_internally.
226 *
227 * ### Thread safety ###
228 * Same as for Peer_socket. (Briefly: all operations safe for simultaneous execution
229 * on separate or the same object.) An informal recommendation, however, is to only use a given
230 * Event_set in one thread. Otherwise things will get confusing, quickly, with no practical benefit of which
231 * I, at least, am aware.
232 *
233 * @internal
234 *
235 * ### Implementation notes ###
236 * The crux of the implementation is in async_wait(), as all other wait types are built on it.
237 * Therefore there is a giant comment inside that method that is required reading for understanding
238 * this class's innards (which, IMO, are some of the trickiest logic in all of the library).
239 *
240 * As with Peer_socket and Server_socket, much of the implementation (as opposed to interface) of
241 * Event_set functionality resides in class Node. In particular anything to do with thread W is in
242 * Node. The actual code is in event_set.cpp, but since the logic involves Node state, and
243 * Event_set is subservient to the Node, in terms of objects it makes more sense to keep it in
244 * class Node. However, when no Node state is involved, Event_set logic is actually typically
245 * coded in Event_set methods, to a greater extent than in Peer_socket or Server_socket, which are
246 * mere data stores in comparison.
247 */
249 // Endow us with shared_ptr<>s ::Ptr and ::Const_ptr (syntactic sugar).
250 public util::Shared_ptr_alias_holder<boost::shared_ptr<Event_set>>,
251 // Allow access to Ptr{this} from inside Event_set methods. Just call shared_from_this().
252 public boost::enable_shared_from_this<Event_set>,
253 public log::Log_context,
254 private boost::noncopyable
255{
256public:
257 // Types.
258
259 /// A state of an Event_set.
260 enum class State
261 {
262 /**
263 * Default state; valid Event_set that is not currently waiting on events. All user
264 * operations are valid in this state.
265 */
266 S_INACTIVE,
267 /**
268 * Waiting state: valid Event_set that is currently waiting on previously described events. In
269 * this state only async_wait_finish() may be called without resulting in an error.
270 */
271 S_WAITING,
272 /// Node has disowned the Peer_socket; all further operations will result in error.
273 S_CLOSED
274 }; // enum class State
275
276 /**
277 * Type of event or condition of interest supported by class Event_set. When specifying interest in some socket
278 * reaching a certain condition, or when requesting the results of that interest, the user essentially specifies
279 * a pair of data: an enumeration value of this type and a socket of a certain type (that type is specified in
280 * the very name of the #Event_type). For example, I may be interested in Event_type::S_PEER_SOCKET_READABLE
281 * becoming true for Peer_socket::Ptr `sock`. The precise meaning is documented for each enumeration value.
282 *
283 * @internal
284 *
285 * ### Implementation notes ###
286 * You will note a few different structures, such as Event_set::m_want and Event_set::m_can, are keyed by this
287 * type. Doing it that way, instead of simply having a simpler Event_set::m_want-like structure (etc.) exist 3x,
288 * has its plusses and minuses. Historically, this was actually implemented that other way first, but I wanted
289 * to play with `boost::any` to see if it makes the code more elegant. It has certainly resulted in significantly
290 * fewer methods and less code; and in code that is more generic (and, in principle, extensible if we somehow
291 * come up with another event type of interest); and less bug-prone. The code is also arguably more opaque and
292 * harder to grok right off the bat, as it's more abstract. Finally, from the user's point of view, it is slightly
293 * harder to use in that when emitting results of an `Event_set::[a]sync_wait()`,
294 * one must `any_cast<>` to the proper socket type -- easy but requires a small learning curve. I'll
295 * say overall it is better this way than the other way.
296 *
297 * In terms of extending this `enum`, which seems unlikely, the following would be involved. Add a value for
298 * the `enum`; then add clauses for it in Socket_as_any_hash::operator(), Socket_as_any_equals::operator(),
299 * Event_set::sock_as_any_to_str(). Extend the structures in Event_set::empty_ev_type_to_socks_map() and
300 * `S_EV_TYPE_TO_IS_ACTIVE_NODE_MTD`. The latter will need a new method written in Node that checks for
301 * whether the condition of this type currently holds for the given socket -- whose type, by the way, you will
302 * need to decide and document in the doc header for the new `enum` value. Finally, you'll need to find all
303 * situations throughout the code where the condition may change from not holding to holding and possibly
304 * save it into Node::m_sock_events when detected (for example, see when `m_sock_events[S_PEER_SOCKET_READABLE]`
305 * is `insert()`ed into).
306 */
307 enum class Event_type
308 {
309 /**
310 * Event type specifying the condition of interest wherein a target `Peer_socket sock` is such that
311 * calling `sock->receive()` would yield either non-zero ("successfully dequeued
312 * received data") or zero and an error (but not zero and NO error). In other words, specifies
313 * the condition where a Peer_socket is Readable.
314 *
315 * In Event_set::Sockets structures associated with this Event_set::Event_type, `boost::any` elements
316 * wrap the type: Peer_socket::Ptr. `boost::any_cast<>` to that type to obtain the socket.
317 */
318 S_PEER_SOCKET_READABLE,
319
320 /**
321 * Event type specifying the condition of interest wherein a target `Peer_socket sock` is such that
322 * calling `sock->send()` with a non-empty buffer would yield either non-zero ("successfully enqueued
323 * data to be sent") or zero and an error (but not zero and NO error). In other words, specifies
324 * the condition where a Peer_socket is Writable.
325 *
326 * In Event_set::Sockets structures associated with this Event_set::Event_type, `boost::any` elements
327 * wrap the type: Peer_socket::Ptr. `boost::any_cast<>` to that type to obtain the socket.
328 */
329 S_PEER_SOCKET_WRITABLE,
330
331 /**
332 * Event type specifying the condition of interest wherein a target `Server_socket serv` is such that
333 * calling `serv->accept()` would yield either non-null ("successfully accepted a ready conneection")
334 * or null and an error (but not null and NO error). In other words, specifies
335 * the condition where a Server_socket is Acceptable.
336 *
337 * In Event_set::Sockets structures associated with this Event_set::Event_type, `boost::any` elements
338 * wrap the type: Server_socket::Ptr. `boost::any_cast<>` to that type to obtain the socket.
339 */
340 S_SERVER_SOCKET_ACCEPTABLE
341 }; // enum class Event_type
342
343 class Socket_as_any_hash;
344 class Socket_as_any_equals;
345
346 /**
347 * A set of sockets of one type, used to communicate sets of desired and resulting events in various Event_set
348 * APIs. As a rule, a given #Sockets object will store sockets of one underlying type; meaning
349 * the `boost::any`s stored inside one such set can ALL be `boost::any_cast<>` to the *same* type. Which type that
350 * is is usually determined by the associated #Event_type value, typically supplied alongside a #Sockets set
351 * in another argument. For example, if `ev_type == Event_type::S_PEER_SOCKET_READABLE`, then every `boost::any`
352 * in the set can be decoded as follows: `Peer_socket::Ptr sock = any_cast<Peer_socket::Ptr>(sock_as_any)`, where
353 * `sock_as_any` is an element in a #Sockets.
354 *
355 * As of this writing, the type is chronologically ordered; meaning sockets will be stored in order from latest to
356 * oldest to be inserted into the structure. E.g., emit_result_sockets() will produce a set containing of
357 * readable sockets, in reverse chronological order in which they were detected as being readable. This may or may
358 * not be useful in debugging.
359 *
360 * @internal
361 *
362 * This type is also used internally extensively.
363 *
364 * @todo Is it necessary to have Event_set::Sockets be aliased to util::Linked_hash_set? `unordered_set` would also
365 * work and take somewhat less memory and computational overhead. It would become unordered, instead of ordered
366 * chronologically, but that seems like a price possibly worth paying.
367 *
368 * Note, also, the to-do in emit_result_sockets() doc header, regarding using `variant` instead of `any`.
369 * Not only would that be faster and arguably safer, being compile-time in nature; but we'd get
370 * hashing/equality for free -- hence the code would be much pithier (no need for Socket_as_any_hash or
371 * Socket_as_any_equals).
372 */
374
375 /**
376 * The type for custom handler passed to async_wait(), which is executed when one or more active events detected, or
377 * interrupted as if by signal.
378 *
379 * @internal
380 *
381 * @todo Perhaps async_wait() and other APIs of Event_set taking handlers should be templated on handler type
382 * for syntactic sugar. Though, currently, this would be no faster (it is internally stored as this type anyway and
383 * must be so), nor would it actually improve call code which needs no explicit cast (an object of this type will
384 * implicitly be substituted as a conversion from whatever compatible-with-this-signature construction they used).
385 * So on balance, this currently appears superior. After all writing non-template bodies is easier/nicer.
386 */
387 using Event_handler = Function<void (bool)>;
388
389 // Constructors/destructor.
390
391 /// Boring destructor. Note that deletion is to be handled exclusively via `shared_ptr`, never explicitly.
392 ~Event_set();
393
394 // Methods.
395
396 /**
397 * Current State of the Event_set. Note that this may change the moment the method returns.
398 *
399 * @return Ditto.
400 */
401 State state() const;
402
403 /**
404 * Node that produced this Event_set. Note that this may change the moment the method returns
405 * (but only to null).
406 *
407 * @return Pointer to (guaranteed valid) Node; null if state() is `S_CLOSED`.
408 */
409 Node* node() const;
410
411 /**
412 * Clears all stored resources (any desired events, result events, and any handler saved by
413 * async_wait()) and moves state to State::S_CLOSED. In particular Node will have disowned this object
414 * by the time close() returns.
415 *
416 * You might call close() while state is State::S_WAITING, but if a timeout-less sync_wait() is executing
417 * in another thread, it will NEVER return. Similarly, if state is currently WAITING due to
418 * async_wait(), the handler saved by async_wait() will NEVER be called. So don't do that.
419 * However, first closing one or more sockets being waited on by those calls and THEN calling
420 * `this->close()` is perfectly safe, in that sync_wait() will exit, or the handler will be called.
421 * (In fact when Node shuts down it does just that.)
422 *
423 * @param err_code
424 * See flow::Error_code docs for error reporting semantics. Generated codes:
425 * error::Code::S_EVENT_SET_CLOSED.
426 */
427 void close(Error_code* err_code = nullptr);
428
429 /**
430 * Adds the given socket to the set of sockets we want to know are "ready" by the definition of
431 * the given event type. See individual Event_type enumeration members' doc comments for exact
432 * definition of readiness for each #Event_type. For example, Event_type::S_PEER_SOCKET_READABLE
433 * means we want to know when `sock->receive()` would yield either some data or an error, but not
434 * no data and no error.
435 *
436 * @tparam Socket type to which `ev_type` applies. E.g., Peer_socket for PEER_SOCKET_READABLE.
437 * @param sock
438 * Socket to add. Must be from the same Node as the one originating this Event_set.
439 * @param ev_type
440 * The condition we are interested in `sock` reaching.
441 * @param err_code
442 * See flow::Error_code docs for error reporting semantics. Generated codes:
443 * error::Code::S_EVENT_SET_ALREADY_EXISTS, error::Code::S_EVENT_SET_CLOSED,
444 * error::Code::S_EVENT_SET_IMMUTABLE_WHEN_WAITING.
445 * @return `true` if and only if no error occurred (`*err_code` is success).
446 */
447 template<typename Socket>
448 bool add_wanted_socket(typename Socket::Ptr sock, Event_type ev_type, Error_code* err_code = nullptr);
449
450 /**
451 * Opposite of add_wanted_socket().
452 *
453 * @tparam See add_wanted_socket().
454 * @param sock
455 * Socket to remove.
456 * @param ev_type
457 * See add_wanted_socket().
458 * @param err_code
459 * See flow::Error_code docs for error reporting semantics. Generated codes:
460 * error::Code::S_EVENT_SET_EVENT_DOES_NOT_EXIST, error::Code::S_EVENT_SET_CLOSED,
461 * error::Code::S_EVENT_SET_IMMUTABLE_WHEN_WAITING.
462 * @return `true` if and only if no error occurred (`*err_code` is success).
463 */
464 template<typename Socket>
465 bool remove_wanted_socket(typename Socket::Ptr sock, Event_type ev_type, Error_code* err_code = nullptr);
466
467 /**
468 * Efficiently exchanges the current set of sockets we want to know are "ready" by the definiton of
469 * the given event type. See individual Event_type enumeration members' doc comments for exact
470 * definition of readiness for each #Event_type. For example, Event_type::S_PEER_SOCKET_READABLE
471 * means we want to know when `sock->receive()` would yield either some data or an error, but not
472 * no data and no error. Use this to perform arbitrarily complex operations on the internal set
473 * storing sockets of interest for the given event type `ev_type`, when the add_wanted_socket() and
474 * remove_wanted_socket() methods are insufficient. For example:
475 *
476 * ~~~
477 * Event_set::Sockets socks;
478 * // Exchange of our empty `socks` with what's in `es`.
479 * es->swap_wanted_sockets(&socks, Event_type::S_PEER_SOCKET_READBLE);
480 * // ...Remove every 3rd socket from `socks`, and log `socks.size()`....
481 * // Now put the modified socket set back into `es`.
482 * es->swap_wanted_sockets(&socks, Event_type::S_PEER_SOCKET_READBLE);
483 * ~~~
484 *
485 * ### Rationale ###
486 * The swap paradigm (precursor to the "move" paradigm added in C++11) allows
487 * arbitrarily complex operations without sacrificing performance or thread safety.
488 *
489 * @param target_set
490 * Pointer to set of sockets to which to load the current internal set. Currently
491 * contained sockets must be from the same Node that originated this Event_set.
492 * @param ev_type
493 * See add_wanted_socket().
494 * @param err_code
495 * See flow::Error_code docs for error reporting semantics. Generated codes:
496 * error::Code::S_EVENT_SET_CLOSED, error::Code::S_EVENT_SET_IMMUTABLE_WHEN_WAITING.
497 * @return `true` if and only if no error occurred (`*err_code` is success).
498 */
499 bool swap_wanted_sockets(Sockets* target_set, Event_type ev_type, Error_code* err_code);
500
501 /**
502 * Identical to `swap_wanted_sockets(&sockets, ev_type, err_code)`, where originally `sockets` is empty and
503 * is afterwards cleared; but more efficient.
504 *
505 * @param ev_type
506 * See swap_wanted_sockets().
507 * @param err_code
508 * See flow::Error_code docs for error reporting semantics. Generated codes:
509 * error::Code::S_EVENT_SET_CLOSED, error::Code::S_EVENT_SET_IMMUTABLE_WHEN_WAITING.
510 * @return `true` if and only if no error occurred (`*err_code` is success).
511 */
512 bool clear_wanted_sockets(Event_type ev_type, Error_code* err_code = nullptr);
513
514 /**
515 * Returns `true` if and only if at least one wanted event for at least one socket is registered
516 * (via add_wanted_socket(), swap_wanted_sockets(), etc.).
517 *
518 * @param err_code
519 * See flow::Error_code docs for error reporting semantics. Generated codes:
520 * error::Code::S_EVENT_SET_CLOSED.
521 * @return `true` if there are wanted events; `false` if there are no wanted events (then `*err_code` is
522 * success) or there was an error (`*err_code` is failure; i.e., `bool(*err_code) == true`).
523 */
524 bool events_wanted(Error_code* err_code = nullptr) const;
525
526 /**
527 * Checks for all previously described events that currently hold, saves them for retrieval via
528 * emit_result_sockets(), etc., and returns. This is akin to a non-blocking sync_wait() (which does
529 * not exist; poll() does), a/k/a a `select()` with a timeout of zero.
530 *
531 * In a non-error invocation, state() will be State::S_INACTIVE before and after the call. In an error
532 * invocation, state() will not change.
533 *
534 * @param err_code
535 * See flow::Error_code docs for error reporting semantics. Generated codes:
536 * error::Code::S_EVENT_SET_CLOSED, error::Code::S_EVENT_SET_DOUBLE_WAIT_OR_POLL.
537 * @return `true` if and only if no error occurred (`*err_code` is success).
538 */
539 bool poll(Error_code* err_code = nullptr);
540
541 /**
542 * Blocks indefinitely until one or more of the previously described events hold -- or the wait
543 * is interrupted; saves them for retrieval via emit_result_sockets(), etc.; and returns.
544 * This is akin to a `select()` call with no (i.e., infinite) timeout.
545 *
546 * The special case of Node::interrupt_all_waits() interrupting this wait -- which is conceptually similar
547 * to `EINTR` in POSIX -- manifests itself as error::Code::S_WAIT_INTERRUPTED. In this case,
548 * emit_result_sockets() (etc.) should not be used, as one should assume no events are active due to the
549 * interruption.
550 *
551 * In a non-error invocation, state() will be State::S_INACTIVE before and after the call, unless
552 * underlying Node is destroyed, in which case the final state may be State::S_CLOSED. In an error
553 * invocation, state() will not change, and the method will return immediately. Additionally, the
554 * method will NEVER return, if another thread calls `this->close()` or `this->async_wait_finish()`
555 * during this sync_wait() (so don't do that).
556 *
557 * @param err_code
558 * See flow::Error_code docs for error reporting semantics. Generated codes:
559 * error::Code::S_WAIT_INTERRUPTED, error::Code::S_EVENT_SET_NO_EVENTS,
560 * error::Code::S_EVENT_SET_DOUBLE_WAIT_OR_POLL, error::Code::S_EVENT_SET_CLOSED.
561 * @return `true` if and only if no error occurred (`*err_code` is success).
562 */
563 bool sync_wait(Error_code* err_code = nullptr);
564
565 /**
566 * Same as the other sync_wait() but will stop waiting if the timeout given as argument
567 * expires. If the timeout expires, it is the error code error::Code::S_WAIT_USER_TIMEOUT. This is akin
568 * to a `select()` call with a finite timeout.
569 *
570 * An additional error situation is possible in addition to that described in the 2nd/3rd paragraphs of
571 * the other sync_wait()'s doc header: if this is `close()`d during the wait, and the wait
572 * times out, error::Code::S_EVENT_SET_CLOSED will be emitted when this timeout is detected. On the
573 * positive side, that means `sync_wait(timeout)` will eventually exit no matter what.
574 *
575 * Tip: Typical types you might use for `max_wait`: `boost::chrono::milliseconds`,
576 * `boost::chrono::seconds`, `boost::chrono::high_resolution_clock::duration`.
577 *
578 * No guarantees are made as to the accuracy of the timeout timer, although you can optimistically
579 * provide arbitrarily precise values for `max_wait`.
580 *
581 * @tparam Rep
582 * See `boost::chrono::duration` documentation (and see above tip).
583 * @tparam Period
584 * See `boost::chrono::duration` documentation (and see above tip).
585 * @param max_wait
586 * The maximum amount of time from now to wait before giving up on the wait and returning.
587 * `"duration<Rep, Period>::max()"` will eliminate the time limit and cause indefinite wait.
588 * @param err_code
589 * See flow::Error_code docs for error reporting semantics. Generated codes:
590 * Same as the other sync_wait() plus: error::Code::S_WAIT_USER_TIMEOUT.
591 * @return `true` if and only if no error occurred (`*err_code` is success). Timeout expiring IS
592 * an error, in particular.
593 */
594 template<typename Rep, typename Period>
595 bool sync_wait(const boost::chrono::duration<Rep, Period>& max_wait, Error_code* err_code = nullptr);
596
597 /**
598 * Moves object to State::S_WAITING state, saves the given handler to be executed later (in a different,
599 * unspecified thread), when one or more of the previously described events hold; and immediately
600 * returns. State will go back to State::S_INACTIVE when the handler fires; or when async_wait_finish() is
601 * called by the user (whichever happens first). State may also change to State::S_CLOSED if `this->close()` is
602 * called, or the Node is destroyed. The saved handler will be forgotten at that time. Once
603 * INACTIVE is entered, emit_result_sockets(), etc., are to be used to access the detected
604 * events. on_event() must take one bool argument. If this argument is `false`, use emit_result_sockets(),
605 * etc., to access the detected events. If this argument is `true`, then Node::interrupt_all_waits() was
606 * invoked and has interrupted this wait (conceptually similar to `EINTR` in POSIX). In the latter case,
607 * do no use emit_result_sockets(), etc., as no events are active due to the interruption.
608 *
609 * In a non-error invocation, state() will be INACTIVE before the call and WAITING after it.
610 * In an error invocation, state() will not change, and the method will return immediately.
611 * Additionally, on_event() will NEVER be called, if another thread calls `this->close()` before
612 * async_wait_finish() is called, and before the Node is destroyed. So don't do that.
613 *
614 * Restrictions on what `on_event()` is allowed to do: It is allowed to do anything except make any
615 * `net_flow` call related to the net_flow::Node originating the current Event_set; doing so results in
616 * undefined behavior. Informally, it also must not block; spending significant time in
617 * `on_event()` will disrupt the functionality of the Node. Even more informally, the goal of
618 * `on_event()` should be to quickly signal the user's thread(s) that the events hold (using the
619 * technique of the user's choice) and then return -- beyond that, the handling of the ready events
620 * should be in the user's thread(s).
621 *
622 * Tip: Call async_wait_finish() before checking the saved results, using emit_result_sockets(). Doing so BEFORE
623 * any events are detected will finish this asynchronous wait. Doing so AFTER any events are
624 * detected will be a harmless NOOP.
625 *
626 * Tip: Use lambdas (or `bind()`) to make async_wait() asynchronously call any arbitrary function
627 * or method with any arbitrary arguments -- NOT just a free `void` function with 1 argument. Outside the scope
628 * of discussion here, but if this doesn't ring a bell, please look into lambdas (`bind()` as a backup).
629 *
630 * Rationale for no timeout argument: Since the caller of async_wait() retains flow control
631 * without blocking, the user code can enforce its own timeout logic, if necessary, and simply
632 * call async_wait_finish() when desired. In fact that is just what sync_wait() (with timeout argument) does
633 * internally.
634 *
635 * @param on_event
636 * The function to call as soon as as one or more events previously described hold, AND
637 * `this->state()` is still State::S_WAITING. (Also see above tip.)
638 * `on_event(bool was_interrupted)` will be called.
639 * @param err_code
640 * See flow::Error_code docs for error reporting semantics. Generated codes:
641 * error::Code::S_EVENT_SET_DOUBLE_WAIT_OR_POLL, error::Code::S_EVENT_SET_CLOSED.
642 * @return `true` if and only if no error occurred (`*err_code` is success).
643 */
644 bool async_wait(const Event_handler& on_event, Error_code* err_code = nullptr);
645
646 /**
647 * Moves object from State::S_WAITING to State::S_INACTIVE, and forgets any handler saved by async_wait(), or does
648 * nothing if state is already INACTIVE. Use this to cut short an asynchronous wait started by
649 * async_wait(). After return, emit_result_sockets(), etc., can be used to check the active
650 * events (if any) detected during the last wait.
651 *
652 * In a non-error invocation, state() will be State::S_INACTIVE or State::S_WAITING before the call and
653 * State::S_INACTIVE after it. In an error invocation, state() will not change.
654 *
655 * You might call async_wait_finish() while another thread is executing a timeout-less sync_wait()
656 * (which is also invoked by blocking methods like Peer_socket::sync_receive()). However that
657 * will cause that sync_wait() to NEVER return. So don't do that.
658 *
659 * @param err_code
660 * See flow::Error_code docs for error reporting semantics. Generated codes:
661 * error::Code::S_EVENT_SET_CLOSED.
662 * @return `true` if and only if no error occurred (`*err_code` is success). In particular, state()
663 * being State::S_INACTIVE when the method starts is not an error.
664 */
665 bool async_wait_finish(Error_code* err_code = nullptr);
666
667 /**
668 * Returns `true` if and only if the last wait, if any, detected at least one event. In other
669 * words, returns `true` if and only if emit_result_sockets() would currently emit at least one
670 * socket, if tried with all possible Event_type.
671 *
672 * One can still use `emit_result_sockets()` to get the specific events after calling this.
673 *
674 * @note Conceptually, this is a bit like when `select()` returns 0 or higher; and one uses the check
675 * of whether its return value is 0 or non-zero. Non-zero is actually some complex index thing,
676 * but often that detail is not necessary (much like `emit_result_sockets()` is unnecessary, analogously),
677 * as the mere presence or absence of 1+ events is enough information. For example, if only one event
678 * for one socket is being waited on, one can check this and confidently perform the appropriate I/O
679 * operation for that one socket, if and only if this returns `true` -- or `select()` would return
680 * non-zero. Slightly more wastefully, but still not bad at all, is when (say) 2 event types are being
681 * waited on, but for only 1 socket. In that case `true` return => just perform both I/O operations;
682 * one OR both of them should yield something (and the one that doesn't hardly uses any resources).
683 * Similarly, even if you're waiting on a few sockets, if it's a limited number (like, say, 2-3), then
684 * indiscriminately trying all possible I/O on all 2-3 sockets is only slightly wasteful: and the code
685 * is quite a bit shorter than carefully checking `emit_result_sockets()` (or doing `FD_ISSET()`, etc., in
686 * the analogous `select()` code).
687 * @param err_code
688 * See flow::Error_code docs for error reporting semantics. Generated codes:
689 * error::Code::S_EVENT_SET_CLOSED, error::Code::S_EVENT_SET_RESULT_CHECK_WHEN_WAITING.
690 * @return `true` if there are active events; `false` if there are no active events (then `*err_code` is
691 * success) or there was an error (`*err_code` is failure; i.e., `bool(*err_code) == true`).
692 */
693 bool events_detected(Error_code* err_code = nullptr) const;
694
695 /**
696 * Gets the sockets that satisfy the condition of the given Event_type detected during the last wait.
697 * More precisely, moves all sockets satisfying that condition detected during the last wait (if any)
698 * into the set provided by the user. Because it is a move (for efficiency among other reasons), the
699 * subsequent calls to the same method will yield empty sets (until the next wait operation).
700 * Calling before any wait will also yield an empty set.
701 *
702 * Note that the accumulated sockets are NOT preserved across waits. That is, if you
703 * start a wait, the preceding wait's results are wiped out.
704 *
705 * ### Rationale ###
706 * Making the method a one-off that returns nothing after the first invocation (per
707 * wait) allows for thread safety without sacrificing efficiency by adding set copy.
708 *
709 * ### How to use ###
710 * First, prepare a (usually empty) target socket set structure. Second, call emit_result_sockets() to transfer
711 * the results to it. Third, for each socket of interest, `any_cast<>` it from `boost::any` to the
712 * socket pointer of the appropriate type. (Recall that `boost::any` stores an object of any type
713 * inside it, so to get access to that you must know to what to cast it; but this is easy, since by
714 * specifying `ev_type` you are implying a certain socket type.) Example:
715 *
716 * ~~~
717 * Event_set::Sockets readable_socks; // Note this contains boost::any's as elements, regardless of `ev_type`.
718 * event_set->emit_result_sockets(&readable_socks, Event_set::Event_type::S_PEER_SOCKET_READABLE);
719 * for (const auto& readable_sock_as_any : readable_socks)
720 * {
721 * // Since we asked for S_PEER_SOCKET_READABLE, we know results are all Peer_sockets. Cast to that type:
722 * const Peer_socket::Ptr readable_sock = boost::any_cast<Peer_socket::Ptr>(readable_sock_as_any);
723 * // PEER_SOCKET_READABLE indicates readiness to receive() to yield data or an error. We can now do so!
724 * readable_sock->receive(...); // Details of this call left to reader.
725 * }
726 * ~~~
727 *
728 * @param target_set
729 * Pointer to set of sockets to which to load the current internal set of result sockets
730 * of type `ev_type` found during the last wait. Any elements here at call time will be removed.
731 * @param ev_type
732 * The condition we are interested in which sockets have reached during the last wait.
733 * @param err_code
734 * See flow::Error_code docs for error reporting semantics. Generated codes:
735 * error::Code::S_EVENT_SET_CLOSED, error::Code::S_EVENT_SET_IMMUTABLE_WHEN_WAITING.
736 * @return `true` if and only if no error occurred (`*err_code` is success).
737 *
738 * @todo Event_set::emit_result_sockets() sets a #Sockets structure which stores `boost:any`s each of which
739 * stores either a `Peer_socket::Ptr` or a `Server_socket::Ptr`; #Sockets should be changed to store
740 * C++17 `std::variant`s. Performance, both internally and externally, would improve by using this
741 * type-safe compile-time mechanism (which is akin to `union`s but much more pleasant to use).
742 * At the time this feature was written, Flow was in C++11, so `variant`s were not available, and
743 * the author wanted to play around with `any`s instead of haxoring old-school `union`s.
744 * `variant` is much nicer, however, and the dynamic nature of `any` is entirely unnecessary here.
745 */
746 bool emit_result_sockets(Sockets* target_set, Event_type ev_type, Error_code* err_code = nullptr);
747
748 /**
749 * Identical to `emit_result_sockets(&sockets, ev_type, err_code)`, where originally `sockets` is empty and
750 * is afterwards cleared; but more efficient.
751 *
752 * @param ev_type
753 * See emit_result_sockets().
754 * @param err_code
755 * Same.
756 * @return Same.
757 */
758 bool clear_result_sockets(Event_type ev_type, Error_code* err_code = nullptr);
759
760 /**
761 * Forgets all sockets stored in this object in any fashion.
762 *
763 * @param err_code
764 * See flow::Error_code docs for error reporting semantics. Generated codes:
765 * error::Code::S_EVENT_SET_CLOSED, error::Code::S_EVENT_SET_IMMUTABLE_WHEN_WAITING.
766 * @return true if and only if no error occurred (*err_code is success).
767 */
768 bool clear(Error_code* err_code = nullptr);
769
770private:
771 // Friends.
772
773 /**
774 * See rationale for `friend`ing Node in class Event_set documentation header.
775 * @see Node.
776 */
777 friend class Node;
778
779 // Types.
780
781 /**
782 * Short-hand for reentrant mutex type. We explicitly rely on reentrant behavior, so this isn't "just in case."
783 * (One shouldn't use reentrant mutexes "just in case"; it should be entirely conscious and on-purpose; one should
784 * use non-reentrant mutexes, all else being equal.)
785 *
786 * @todo This doc header for Event_set::Mutex should specify what specific behavior requires mutex reentrance, so that
787 * for example one could reevaluate whether there's a sleeker code pattern that would avoid it.
788 */
790
791 /// Short-hand for RAII lock guard of #Mutex. Use instead of `boost::lock_guard` for `release()` at least.
793
794 /**
795 * Short-hand for type storing a set of socket sets -- one per possible #Event_type `enum` value.
796 * In practice, the key set for a value of this type is all Event_type members; use
797 * empty_ev_type_to_socks_map() to create a maximally empty such structure.
798 */
800
801 // Constructors.
802
803 /**
804 * Constructs object; initializes all values to well-defined but possibly meaningless values (0,
805 * empty, etc.).
806 *
807 * @param logger_ptr
808 * The Logger implementation to use subsequently.
809 */
810 explicit Event_set(log::Logger* logger_ptr);
811
812 // Methods.
813
814 /**
815 * Helper that ensures the state of `*this` is such that one may modify the #m_can and #m_want
816 * socket sets. Pre-condition: #m_mutex is locked.
817 *
818 * @param err_code
819 * If `false` returned, sets this to the reason why socket sets are not OK to modify.
820 * Otherwise sets it to success. Possible errors:
821 * error::Code::S_EVENT_SET_CLOSED, error::Code::S_EVENT_SET_IMMUTABLE_WHEN_WAITING.
822 * @return `true` if OK to modify; `false` if not OK to modify.
823 */
824 bool ok_to_mod_socket_set(Error_code* err_code) const;
825
826 /**
827 * Same as the public `sync_wait(max_wait)` but uses a `Fine_clock`-based `Fine_duration` non-template
828 * type for implementation convenience and to avoid code bloat in specifying timeout.
829 *
830 * @param max_wait
831 * See the public sync_wait() *with* a `max_wait` argument. `"duration<Rep, Period>::max()"` maps to the value
832 * `Fine_duration::max()` for this argument.
833 * @param err_code
834 * See sync_wait().
835 * @return See sync_wait().
836 */
837 bool sync_wait_impl(const Fine_duration& max_wait, Error_code* err_code);
838
839 /**
840 * Creates a maximally empty #Ev_type_to_socks_map: it will have all possible Event_type as keys
841 * but only empty #Sockets sets as values.
842 *
843 * @return Ditto.
844 */
846
847 /**
848 * Helper that clears each #Sockets set inside an #Ev_type_to_socks_map. Thus,
849 * it is equivalent to `*ev_type_to_socks_map = empty_ev_type_to_socks_map()`, but perhaps faster.
850 *
851 * @param ev_type_to_socks_map
852 * Target map.
853 */
854 static void clear_ev_type_to_socks_map(Ev_type_to_socks_map* ev_type_to_socks_map);
855
856 /**
857 * Functional helper that checks whether a given `pair` in an #Ev_type_to_socks_map contains an empty
858 * set of #Sockets or not.
859 *
860 * @param ev_type_and_socks
861 * A value (key and mapped, not just mapped) from an #Ev_type_to_socks_map.
862 * @return `true` if and only if the socket set is empty.
863 */
864 static bool ev_type_to_socks_map_entry_is_empty(const Ev_type_to_socks_map::Value& ev_type_and_socks);
865
866 /**
867 * Helper that returns a loggable string summarizing the sizes of the socket sets, by type, stored in
868 * an #Ev_type_to_socks_map.
869 *
870 * @param ev_type_to_socks_map
871 * A valid such map.
872 * @return Loggable string.
873 */
874 static std::string ev_type_to_socks_map_sizes_to_str(const Ev_type_to_socks_map& ev_type_to_socks_map);
875
876 /**
877 * Helper that returns a loggable string representing the socket stored in the given `boost::any` that
878 * stores a value allowed by the members of #Event_type `enum`.
879 *
880 * @param sock_as_any
881 * See above. `sock_as_any.empty()` is also allowed.
882 * @return Loggable string.
883 */
884 static std::string sock_as_any_to_str(const boost::any& sock_as_any);
885
886 // Constants.
887
888 /**
889 * Mapping from each possible #Event_type to the Node method that determines whether the condition defined by
890 * that #Event_type is currently true for the socket wrapped in the `boost::any` argument passed to the method.
891 *
892 * E.g., `bool Node::sock_is_readable(const boost::any sock_as_any) const` is to return true if and only if
893 * `sock = boost::any_cast<Peer_socket::Ptr>(sock_as_any)` -- which is a Peer_socket::Ptr -- would yield non-zero
894 * or zero and error if one were to execute `sock->receive()`. Note that the latter condition is defined by the
895 * doc comment on Event_type::S_PEER_SOCKET_READABLE.
896 */
897 static const boost::unordered_map<Event_type, Function<bool (const Node*, const boost::any&)>>
899 // Data.
900
901 /// See state(). Should be set before user gets access to `*this`. Must not be modified by non-W threads after that.
903
904 /// See node(). Should be set before user gets access to `*this`. Must not be modified by non-W threads after that.
906
907 /**
908 * The sockets, categorized by #Event_type of interest, to check for "ready" status (as defined in the doc header
909 * for each #Event_type), in the next wait (State::S_WAITING state).
910 */
912
913 /**
914 * The sockets, categorized by #Event_type of interest, that were found to be "ready" (as defined in the doc header
915 * for each #Event_type), during the last wait (State::S_WAITING state). For each WAITING period, each set in
916 * #m_can following that period must be a subset of the corresponding #m_want set when entering that period.
917 *
918 * E.g., `m_can[S_PEER_SOCKET_READABLE]` after WAITING is a subset of `m_want[S_PEER_SOCKET_READABLE]` when just
919 * starting WAITING.
920 */
922
923 /**
924 * During State::S_WAITING, stores the handler (a `void` function with 1 `bool` argument) that will be
925 * called once one or more events are found to hold. `m_on_event.empty()` at all other times.
926 */
928
929 /**
930 * While in State::S_WAITING, if this is `true`, an exhaustive check of all desired events is yet to
931 * be performed (in thread W); if `false`, it has alredy been performed (in thread W), and only
932 * "delta" checks need to be checked from now on during this wait. See details in giant comment
933 * block inside async_wait().
934 */
936
937 /// Mutex protecting ALL data in this object.
938 mutable Mutex m_mutex;
939}; // class Event_set
940
941/**
942 * Hasher class used in storing various sockets of types wrapped as `boost::any`s in the #Sockets type.
943 * We do not simply define `hash_value(any)`, because our implementation specifically works for `any` objects
944 * that store various sockets and won't work for all other possibilities; and we don't want to force this
945 * on every user of `hash<any>`.
946 */
948{
949public:
950 /**
951 * Returns hash value of the given object which must be stored in a #Sockets object.
952 *
953 * @param sock_as_any
954 * Object wrapping one the socket objects permitted by `enum` members of Event_type.
955 * @return Hash.
956 */
957 size_t operator()(const boost::any& sock_as_any) const;
958};
959
960/**
961 * Equality predicate class used in storing various sockets of types wrapped as `boost::any`s in the #Sockets type.
962 * We do not simply define `operator==(any, any)`, because our implementation specifically works for `any` objects
963 * that store various sockets and won't work for all other possibilities; and we don't want to force this
964 * on every user of `hash<any>`.
965 */
967{
968public:
969 /**
970 * Returns whether the two objects, which must be stored in #Sockets objects, are equal by value.
971 *
972 * @param sock_as_any1
973 * Object wrapping one the socket objects permitted by `enum` members of Event_type.
974 * @param sock_as_any2
975 * Object wrapping one the socket objects permitted by `enum` members of Event_type.
976 * @return `true` if and only if the two are equal by value.
977 */
978 bool operator()(const boost::any& sock_as_any1, const boost::any& sock_as_any2) const;
979};
980
981// Free functions: in *_fwd.hpp.
982
983// However the following refer to inner type(s) and hence must be declared here and not _fwd.hpp.
984
985/**
986 * Prints string representation of given Event_set state to given standard `ostream` and returns the
987 * latter.
988 *
989 * @relatesalso Event_set
990 *
991 * @param os
992 * Stream to print to.
993 * @param state
994 * Value to serialize.
995 * @return `os`.
996 */
997std::ostream& operator<<(std::ostream& os, Event_set::State state);
998
999/**
1000 * Prints string representation of given event type to given standard `ostream` and returns the
1001 * latter.
1002 *
1003 * @relatesalso Event_set
1004 *
1005 * @param os
1006 * Stream to print to.
1007 * @param ev_type
1008 * Value to serialize.
1009 * @return `os`.
1010 */
1011std::ostream& operator<<(std::ostream& os, Event_set::Event_type ev_type);
1012
1013// Template implementations.
1014
1015template<typename Socket>
1016bool Event_set::add_wanted_socket(typename Socket::Ptr sock, Event_type ev_type, Error_code* err_code)
1017{
1018 using boost::any;
1019
1020 FLOW_ERROR_EXEC_AND_THROW_ON_ERROR(bool, add_wanted_socket<Socket>, sock, ev_type, _1);
1021 // ^-- Call ourselves and return if err_code is null. If got to present line, err_code is not null.
1022
1023 // We are in thread U != W.
1024
1025 // Accessing m_state, socket sets, etc. which may be written by other threads at any time. Must lock.
1026 Lock_guard lock{m_mutex};
1027
1028 FLOW_LOG_TRACE("Object [" << sock << "] wanted for event type [" << ev_type << "] in Event_set [" << this << "].");
1029
1030 if (!ok_to_mod_socket_set(err_code)) // Ensure we can modify want_set in this state.
1031 {
1032 // *err_code is set.
1033 return false; // Closed; do not set *target_set (*want_set is blank anyway).
1034 }
1035 // else *err_code is success.
1036 assert(!*err_code);
1037
1038 /* Note that this method is a template solely because of the following `any(sock)`. We could've made the user
1039 * perform this conversion themselves and taken a `boost::any` into a non-template method. We give them a little
1040 * sugar though. */
1042 "Expecting amortized constant time insertion sockets container."); // Ensure fastness.
1043 if (!m_want[ev_type].insert(any(sock)).second)
1044 {
1046 }
1047 // else { *err_code is still success. }
1048
1049 return !*err_code;
1050}
1051
1052template<typename Socket>
1053bool Event_set::remove_wanted_socket(typename Socket::Ptr sock, Event_type ev_type, Error_code* err_code)
1054{
1055 FLOW_ERROR_EXEC_AND_THROW_ON_ERROR(bool, remove_wanted_socket<Socket>, sock, ev_type, _1);
1056 // ^-- Call ourselves and return if err_code is null. If got to present line, err_code is not null.
1057
1058 using boost::any;
1059
1060 // We are in thread U != W.
1061
1062 // Accessing m_state, the sets, etc. which may be written by other threads at any time. Must lock.
1063 Lock_guard lock{m_mutex};
1064
1065 FLOW_LOG_TRACE("Object [" << sock << "] no longer wanted for event type [" << ev_type << "] in "
1066 "Event_set [" << this << "].");
1067
1068 if (!ok_to_mod_socket_set(err_code)) // Ensure we can modify want_set in this state.
1069 {
1070 // *err_code is set.
1071 return false; // Closed; do not set *target_set (*want_set is blank anyway).
1072 }
1073 // else *err_code is success.
1074
1075 Sockets& want_set = m_want[ev_type];
1076 /* Note that this method is a template solely because of the following assignment. We could've made the user
1077 * perform this conversion themselves and taken a `boost::any` into an non-template method. We give them a little
1078 * sugar though. */
1079 const any sock_as_any = sock;
1080
1081 const bool did_erase = want_set.erase(sock_as_any) == 1;
1082 if (!did_erase)
1083 {
1085 return false;
1086 }
1087 // else *err_code is success.
1088
1089 return true;
1090} // Event_set::remove_wanted_socket()
1091
1092template<typename Rep, typename Period>
1093bool Event_set::sync_wait(const boost::chrono::duration<Rep, Period>& max_wait, Error_code* err_code)
1094{
1095 assert(max_wait.count() > 0);
1096 return sync_wait_impl(util::chrono_duration_to_fine_duration(max_wait), err_code);
1097}
1098
1099} // namespace flow::net_flow
Convenience class that simply stores a Logger and/or Component passed into a constructor; and returns...
Definition: log.hpp:1786
Interface that the user should implement, passing the implementing Logger into logging classes (Flow'...
Definition: log.hpp:1392
Equality predicate class used in storing various sockets of types wrapped as boost::anys in the Socke...
Definition: event_set.hpp:967
bool operator()(const boost::any &sock_as_any1, const boost::any &sock_as_any2) const
Returns whether the two objects, which must be stored in Sockets objects, are equal by value.
Definition: event_set.cpp:836
Hasher class used in storing various sockets of types wrapped as boost::anys in the Sockets type.
Definition: event_set.hpp:948
size_t operator()(const boost::any &sock_as_any) const
Returns hash value of the given object which must be stored in a Sockets object.
Definition: event_set.cpp:807
A user-set collection of sockets and desired conditions on those sockets (such as: "socket has data t...
Definition: event_set.hpp:255
bool events_detected(Error_code *err_code=nullptr) const
Returns true if and only if the last wait, if any, detected at least one event.
Definition: event_set.cpp:574
Mutex m_mutex
Mutex protecting ALL data in this object.
Definition: event_set.hpp:938
static void clear_ev_type_to_socks_map(Ev_type_to_socks_map *ev_type_to_socks_map)
Helper that clears each Sockets set inside an Ev_type_to_socks_map.
Definition: event_set.cpp:745
bool sync_wait_impl(const Fine_duration &max_wait, Error_code *err_code)
Same as the public sync_wait(max_wait) but uses a Fine_clock-based Fine_duration non-template type fo...
Definition: event_set.cpp:335
Event_type
Type of event or condition of interest supported by class Event_set.
Definition: event_set.hpp:308
static std::string ev_type_to_socks_map_sizes_to_str(const Ev_type_to_socks_map &ev_type_to_socks_map)
Helper that returns a loggable string summarizing the sizes of the socket sets, by type,...
Definition: event_set.cpp:759
State
A state of an Event_set.
Definition: event_set.hpp:261
bool sync_wait(Error_code *err_code=nullptr)
Blocks indefinitely until one or more of the previously described events hold – or the wait is interr...
Definition: event_set.cpp:457
bool add_wanted_socket(typename Socket::Ptr sock, Event_type ev_type, Error_code *err_code=nullptr)
Adds the given socket to the set of sockets we want to know are "ready" by the definition of the give...
Definition: event_set.hpp:1016
util::Mutex_recursive Mutex
Short-hand for reentrant mutex type.
Definition: event_set.hpp:789
State m_state
See state(). Should be set before user gets access to *this. Must not be modified by non-W threads af...
Definition: event_set.hpp:902
Event_handler m_on_event
During State::S_WAITING, stores the handler (a void function with 1 bool argument) that will be calle...
Definition: event_set.hpp:927
bool swap_wanted_sockets(Sockets *target_set, Event_type ev_type, Error_code *err_code)
Efficiently exchanges the current set of sockets we want to know are "ready" by the definiton of the ...
Definition: event_set.cpp:491
static Ev_type_to_socks_map empty_ev_type_to_socks_map()
Creates a maximally empty Ev_type_to_socks_map: it will have all possible Event_type as keys but only...
Definition: event_set.cpp:734
Event_set(log::Logger *logger_ptr)
Constructs object; initializes all values to well-defined but possibly meaningless values (0,...
Definition: event_set.cpp:42
util::Lock_guard< Mutex > Lock_guard
Short-hand for RAII lock guard of Mutex. Use instead of boost::lock_guard for release() at least.
Definition: event_set.hpp:792
bool events_wanted(Error_code *err_code=nullptr) const
Returns true if and only if at least one wanted event for at least one socket is registered (via add_...
Definition: event_set.cpp:550
State state() const
Current State of the Event_set.
Definition: event_set.cpp:60
bool emit_result_sockets(Sockets *target_set, Event_type ev_type, Error_code *err_code=nullptr)
Gets the sockets that satisfy the condition of the given Event_type detected during the last wait.
Definition: event_set.cpp:611
bool ok_to_mod_socket_set(Error_code *err_code) const
Helper that ensures the state of *this is such that one may modify the m_can and m_want socket sets.
Definition: event_set.cpp:673
bool poll(Error_code *err_code=nullptr)
Checks for all previously described events that currently hold, saves them for retrieval via emit_res...
Definition: event_set.cpp:265
bool clear_wanted_sockets(Event_type ev_type, Error_code *err_code=nullptr)
Identical to swap_wanted_sockets(&sockets, ev_type, err_code), where originally sockets is empty and ...
Definition: event_set.cpp:524
bool remove_wanted_socket(typename Socket::Ptr sock, Event_type ev_type, Error_code *err_code=nullptr)
Opposite of add_wanted_socket().
Definition: event_set.hpp:1053
static const boost::unordered_map< Event_type, Function< bool(const Node *, const boost::any &)> > S_EV_TYPE_TO_IS_ACTIVE_NODE_MTD
Mapping from each possible Event_type to the Node method that determines whether the condition define...
Definition: event_set.hpp:898
Node * node() const
Node that produced this Event_set.
Definition: event_set.cpp:66
bool async_wait_finish(Error_code *err_code=nullptr)
Moves object from State::S_WAITING to State::S_INACTIVE, and forgets any handler saved by async_wait(...
Definition: event_set.cpp:214
Ev_type_to_socks_map m_can
The sockets, categorized by Event_type of interest, that were found to be "ready" (as defined in the ...
Definition: event_set.hpp:921
void close(Error_code *err_code=nullptr)
Clears all stored resources (any desired events, result events, and any handler saved by async_wait()...
Definition: event_set.cpp:462
~Event_set()
Boring destructor. Note that deletion is to be handled exclusively via shared_ptr,...
Definition: event_set.cpp:54
bool clear(Error_code *err_code=nullptr)
Forgets all sockets stored in this object in any fashion.
Definition: event_set.cpp:703
bool m_baseline_check_pending
While in State::S_WAITING, if this is true, an exhaustive check of all desired events is yet to be pe...
Definition: event_set.hpp:935
static std::string sock_as_any_to_str(const boost::any &sock_as_any)
Helper that returns a loggable string representing the socket stored in the given boost::any that sto...
Definition: event_set.cpp:775
bool clear_result_sockets(Event_type ev_type, Error_code *err_code=nullptr)
Identical to emit_result_sockets(&sockets, ev_type, err_code), where originally sockets is empty and ...
Definition: event_set.cpp:647
static bool ev_type_to_socks_map_entry_is_empty(const Ev_type_to_socks_map::Value &ev_type_and_socks)
Functional helper that checks whether a given pair in an Ev_type_to_socks_map contains an empty set o...
Definition: event_set.cpp:754
bool async_wait(const Event_handler &on_event, Error_code *err_code=nullptr)
Moves object to State::S_WAITING state, saves the given handler to be executed later (in a different,...
Definition: event_set.cpp:72
Ev_type_to_socks_map m_want
The sockets, categorized by Event_type of interest, to check for "ready" status (as defined in the do...
Definition: event_set.hpp:911
Node * m_node
See node(). Should be set before user gets access to *this. Must not be modified by non-W threads aft...
Definition: event_set.hpp:905
An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...
Definition: node.hpp:934
Properties of various container types.
Definition: traits.hpp:47
std::pair< const Key, Mapped > Value
Short-hand for key/mapped-value pairs stored in the structure.
An object of this class is a set that combines the lookup speed of an unordered_flat_set<> and orderi...
Const_iterator erase(const Const_iterator &it)
Erases the element pointed to by the given valid iterator.
Convenience class template that endows the given subclass T with nested aliases Ptr and Const_ptr ali...
#define FLOW_ERROR_EXEC_AND_THROW_ON_ERROR(ARG_ret_type, ARG_function_name,...)
Narrow-use macro that implements the error code/exception semantics expected of most public-facing Fl...
Definition: error.hpp:363
#define FLOW_ERROR_EMIT_ERROR(ARG_val)
Sets *err_code to ARG_val and logs a warning about the error using FLOW_LOG_WARNING().
Definition: error.hpp:202
#define FLOW_LOG_TRACE(ARG_stream_fragment)
Logs a TRACE message into flow::log::Logger *get_logger() with flow::log::Component get_log_component...
Definition: log.hpp:230
@ S_EVENT_SET_EVENT_ALREADY_EXISTS
Attempted to add an event into an event set, but that event already exists.
@ S_EVENT_SET_EVENT_DOES_NOT_EXIST
Attempted to work with an event that does not exist in the event set.
Flow module containing the API and implementation of the Flow network protocol, a TCP-inspired stream...
Definition: node.cpp:25
std::ostream & operator<<(std::ostream &os, const Congestion_control_selector::Strategy_choice &strategy_choice)
Serializes a Peer_socket_options::Congestion_control_strategy_choice enum to a standard ostream – the...
Definition: cong_ctl.cpp:146
boost::unique_lock< Mutex > Lock_guard
Short-hand for advanced-capability RAII lock guard for any mutex, ensuring exclusive ownership of tha...
Definition: util_fwd.hpp:298
boost::recursive_mutex Mutex_recursive
Short-hand for reentrant, exclusive mutex.
Definition: util_fwd.hpp:251
Fine_duration chrono_duration_to_fine_duration(const boost::chrono::duration< Rep, Period > &dur)
Helper that takes a non-negative duration of arbitrary precision/period and converts it to Fine_durat...
Definition: util.hpp:31
boost::system::error_code Error_code
Short-hand for a boost.system error code (which basically encapsulates an integer/enum error code and...
Definition: common.hpp:497
Fine_clock::duration Fine_duration
A high-res time duration as computed from two Fine_time_pts.
Definition: common.hpp:405