Flow 2.0.0
Flow project: Full implementation reference.
util_fwd.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
22#include <boost/asio.hpp>
23#include <boost/thread.hpp>
24#include <boost/thread/null_mutex.hpp>
25#include <boost/core/span.hpp>
26#include <iostream>
27#include <memory>
28
29/**
30 * Flow module containing miscellaneous general-use facilities that don't fit into any other Flow module.
31 *
32 * Each symbol therein is typically used by at least 1 other Flow module; but all public symbols (except ones
33 * under a detail/ subdirectory) are intended for use by Flow user as well.
34 *
35 * @todo Since Flow gained its first users beyond the original author, some Flow-adjacent code has been written from
36 * which Flow can benefit, including additions to flow::util module. (Flow itself continued to be developed, but some
37 * features were added elsewhere for expediency; this is a reminder to factor them out into Flow for the benefit of
38 * all.) Some features to migrate here might be: conversion between boost.chrono and std.chrono types; (add more
39 * here).
40 */
41namespace flow::util
42{
43// Constants.
44
45/// Configures a #Span at compile-time to have a variable, rather than constant, length (use it as template arg).
46constexpr size_t DYNAMIC_EXTENT = boost::dynamic_extent;
47
48// Types.
49
50// Find doc headers near the bodies of these compound types.
51
52template<typename Key, typename Mapped, typename Hash = boost::hash<Key>, typename Pred = std::equal_to<Key>>
53class Linked_hash_map;
54template<typename Key, typename Hash = boost::hash<Key>, typename Pred = std::equal_to<Key>>
55class Linked_hash_set;
56
57class Null_interface;
58
60template<typename range_t>
62template<typename range_t>
64
65template<typename Value>
66class Scoped_setter;
67
68template<typename Target_ptr,
69 typename Const_target_ptr
70 = typename std::pointer_traits<Target_ptr>::template rebind<typename Target_ptr::element_type const>>
72
73class String_ostream;
74
75template<typename Thread_local_state_t>
77
78template<typename Shared_state_t>
80
82
83/**
84 * Short-hand for standard thread class.
85 * We use/encourage use of boost.thread threads (and other boost.thread facilities) over std.thread counterparts --
86 * simply because it tends to be more full-featured. However, reminder: boost.thread IS (API-wise at least)
87 * std.thread, plus more (advanced?) stuff. Generally, boost.thread-using code can be converted to std.thread
88 * with little pain, unless one of the "advanced?" features is used.
89 */
90using Thread = boost::thread;
91
92/* (The @namespace and @brief thingies shouldn't be needed, but some Doxygen bug necessitated them.
93 * See flow::util::bind_ns for explanation... same thing here.) */
94
95/**
96 * @namespace flow::util::this_thread
97 * @brief Short-hand for standard this-thread namespace. Paired with util::Thread.
98 */
99namespace this_thread = boost::this_thread;
100
101/// Short-hand for an OS-provided ID of a util::Thread.
102using Thread_id = Thread::id;
103
104/**
105 * Short-hand for boost.asio event service, the central class of boost.asio.
106 *
107 * ### Naming ###
108 * The reasons for the rename -- as opposed to simply calling it `Io_service` (historically it was indeed so named) --
109 * are as follows. To start, a later version of Boost (to which we eventually moved) realigned
110 * boost.asio's API to match the feedback boost.asio received when submitted as a candidate for inclusion into
111 * the official STL (sometime after C++17); in this reorg they renamed it from `io_service` to `io_context`.
112 * That's not the actual reason but more of a symptom of similar reasoning to the following:
113 * - "Service" sounds like something that has its own thread(s) perhaps, which `io_service` actually doesn't;
114 * it *can* (and typically is) used to take over at least one thread, but that's not a part of its "essence," so
115 * to speak. I've noticed that when boost.asio neophytes see "service" they intuitively draw incorrect assumptions
116 * about what it does, and then one must repeatedly dash those assumptions.
117 * - Furthermore (though apparently boost.asio guys didn't agree or didn't agree strongly enough) "I/O" implies
118 * an `io_service` is all about working with various input/output (especially networking). While it's true
119 * that roughly 50% of the utility of boost.asio is its portable sockets/networking API, the other 50% is about
120 * its ability to flexibly execute user tasks in various threads; and, indeed, `io_service` *itself* is more about
121 * the latter 50% rather than the former. Its two most basic and arguably oft-used features are simply
122 * `io_service::post()` (which executes the given task ASAP); and the `basic_waitable_timer` set of classes
123 * (which execute task at some specified point in the future). Note these have nothing to do with networking or
124 * I/O of any kind. The I/O comes from the "I/O object" classes/etc., such as `tcp::socket`, but those
125 * are *not* `io_service`; they merely work together with it to execute the user-specified success/failure handlers.
126 *
127 * So, neither "I/O" nor "service" is accurate. To fix both, then, we used this rename reasoning:
128 * - "I/O" can be replaced by the notion of it executing "tasks." boost.asio doesn't use or define the "task" term,
129 * sticking to "handler" or "functor" or "function," but we feel it's a reasonable term in this context.
130 * (Function, etc., doesn't cover all possibilities. Handler is OK, but when it's not in response to any event --
131 * as with vanilla `post()` -- what is it handling?)
132 * - "Service" is trickier to replace. It's a battle between "too generic" and "too specific and therefore long to
133 * type." Plus there's the usual danger of accidentally overloading a term already used elsewhere nearby.
134 * Some ideas considered were: manager, engine, execution engine, queue, queues, context (which boost.asio chose),
135 * and various abbreviations thereof. Ultimately it came down to context vs. engine, and I chose engine because
136 * context is just a little vague, or it suggests an arbitrary grouping of things -- whereas "engine" actually
137 * implies action: want to express this thing provides logical/algorithmic value as opposed to just bundling
138 * stuff together as "context" objects often do (e.g., "SSL context" in openssl). Indeed `io_service` does provide
139 * immense algorithmic value.
140 * - Manager: generic but not bad; clashes with "Windows task manager" and such.
141 * - Execution engine: good but long.
142 * - Queue: early candidate, but at the very least it's not a *single* queue; if there are multiple threads
143 * `io_context::run()`ning then to the extent there are any queues there might be multiple.
144 * - Queues, qs: better... but having a thing called `Task_qs` -- of which there could be multiple (plural) --
145 * was clumsy. (An early proof-of-concept used `Task_qs`; people were not fans.)
146 */
147using Task_engine = boost::asio::io_context;
148
149/// Short-hand for boost.asio strand, an ancillary class that works with #Task_engine for advanced task scheduling.
150using Strand = Task_engine::strand;
151
152/**
153 * boost.asio timer. Can schedule a function to get called within a set amount of time or at
154 * a certain specific time relative to some Epoch.
155 *
156 * @see schedule_task_from_now() (and friends) for a simpler task-scheduling API (which internally uses this
157 * `Timer). The notes below still apply however. Please read them even if you won't use `Timer` directly.
158 *
159 * Important: While one can schedule events using very precise units using #Fine_duration, the
160 * timer may not actually have that resolution. That is, I may schedule something to happen in 1
161 * millisecond and then measure the time passed, using a high-res clock like #Fine_clock, and discover that
162 * the wait was actually 15 milliseconds. This is not a problem for most timers. (In Flow itself, the most advanced
163 * use of timers by far is in flow::net_flow. Timers used in flow::net_flow -- delayed ACK timer, Drop Timer, simulated
164 * latency timer -- typically are for `n x 50` milliseconds time periods or coarser.) However that may not be the
165 * case for all timers. (In particular, flow::net_flow packet pacing may use finer time periods.)
166 *
167 * @note The flow::net_flow references in the present doc header speak of internal implementation details -- not
168 * of interest to the `net_flow` *user*. I leave them in this public doc header for practical purposes, as
169 * examples needed to discuss some Inside-Baseball topics involved.
170 *
171 * So I looked into what boost.asio provides. `deadline_timer` uses the system clock
172 * (`universal_time()`) as the time reference, while `basic_waitable_timer<Fine_clock>` uses the
173 * high-resolution clock (see #Fine_clock). I tested both (using `wait()`s of various lengths
174 * and using #Fine_clock to measure duration) and observed the following resolutions on certain OS
175 * (not listing the hardware):
176 *
177 * - Linux (2.6.x kernel): sub-2 millisecond resolution, with some variance.
178 * (Note: This Linux's `glibc` is too old to provide the `timerfd` API, therefore Boost falls back to
179 * using `epoll_wait()` directly; on a newer Linux this may get better results.)
180 * - Windows 7: 15 millisecond resolution, with little variance.
181 * - macOS: untested. @todo Test macOS timer fidelity.
182 *
183 * These results were observed for BOTH `deadline_timer` and `basic_waitable_timer<Fine_clock>`
184 * in Boost 1.50. Thus, there was no resolution advantage to using the latter -- only an interface advantage.
185 * Conclusion: we'd be well-advised not to rely on anything much smaller than 20 milliseconds when
186 * scheduling timer events. One technique might be, given any time T < 20 ms, to assume T = 0
187 * (i.e., execute immediately). This may or may not be appropriate depending on the situation.
188 *
189 * However, using `basic_waitable_timer<Fine_clock>` may get an additional nice property: #Fine_clock
190 * always goes forward and cannot be affected by NTP or user changes. `deadline_timer` may or may not
191 * be affected by such tomfoolery (untested, but the potential is clearly there). Therefore we do the best
192 * we can by using the #Fine_clock-based timer.
193 *
194 * @todo Upgrade to newer Boost and keep testing timer resolutions on the above and other OS versions.
195 * Update: As of this writing we are on Boost 1.74 now. Needless to say, it is time to reassess the above, as it
196 * has been years since 1.50 -- and we had been on 1.63 and 1.66 for long period of time, let alone 1.74.
197 * Update: No changes with Boost 1.75, the newest version as of this writing.
198 *
199 * @note One annoying, though fully documented, "feature" of this and all boost.asio timers is that `cancel()`ing it
200 * does not always cause the handler to fire with `operation_aborted` error code. Sometimes it was already "just
201 * about" to fire at `cancel()` time, so the handler will run with no error code regardless of the `cancel()`.
202 * Personally I have never once found this behavior useful, and there is much code currently written to work
203 * around this "feature." Furthermore, even a "successful" cancel still runs the handler but with `operation_aborted`;
204 * 99.999% of the time one would want to just not run it at all. Finally, in many cases, even having to create
205 * a timer object (and then the multiple steps required to actually schedule a thing) feels like more boiler-plate
206 * than should be necessary. To avoid all of these usability issues, see schedule_task_from_now() (and similar),
207 * which is a facility that wraps `Timer` for a boiler-plate-free experience sufficient in the majority of practical
208 * situations. `Timer` is to be used directly when that simpler facility is insufficient.
209 *
210 * @note `b_w_t<Fine_clock>` happens to equal `boost::asio::high_resolution_timer`. We chose to alias
211 * in terms of #Fine_clock merely to ensure that #Fine_duration is one-to-one compatible with it, as it
212 * is defined in terms of #Fine_clock also.
213 */
214using Timer = boost::asio::basic_waitable_timer<Fine_clock>;
215
216/// Helper type for setup_auto_cleanup().
217using Auto_cleanup = boost::shared_ptr<void>;
218
219/// Short-hand for the UDP endpoint (IP/port) type.
220using Udp_endpoint = boost::asio::ip::udp::endpoint;
221/// Short-hand for the IPv4 address type.
222using Ip_address_v4 = boost::asio::ip::address_v4;
223/// Short-hand for the IPv6 address type.
224using Ip_address_v6 = boost::asio::ip::address_v6;
225
226/// Short-hand for non-reentrant, exclusive mutex. ("Reentrant" = one can lock an already-locked-in-that-thread mutex.)
227using Mutex_non_recursive = boost::mutex;
228
229/// Short-hand for reentrant, exclusive mutex.
230using Mutex_recursive = boost::recursive_mutex;
231
232/**
233 * Short-hand for non-reentrant, shared-or-exclusive mutex.
234 * When locking one of these, choose one of:
235 * `Lock_guard<Mutex_shared_non_recursive>`, `Shared_lock_guard<Mutex_shared_non_recursive>`.
236 * The level of locking acquired (shared vs. exclusive) depends on which you chose and is thus highly significant.
237 *
238 * @todo Consider changing util::Mutex_shared_non_recursive from `boost::shared_mutex` to `std::shared_mutex`, as
239 * the former has a long-standing unresolved ticket about its impl being slow and/or outdated (as of Boost-1.80).
240 * However see also the note on util::Mutex_shared_non_recursive that explains why it might be best to avoid
241 * this type of mutex altogether in the first place (in most cases).
242 *
243 * ### When to use versus #Mutex_non_recursive ###
244 * Experts suggest fairly strongly that one should be very wary about using a shared mutex, over a simple
245 * non-recursive exclusive mutex, in almost any practical application. The reason there's a trade-off at all is
246 * that a #Mutex_non_recursive is extremely fast to lock and unlock; the entire perf cost is in waiting for
247 * another thread to unlock first; so without contention it's almost *free*. In contrast apparently any real
248 * impl of #Mutex_shared_non_recursive is much slower to lock/unlock. The trade-off is against allowing
249 * reads to proceed in parallel; but experts say this is "worth it" only when these read critical sections
250 * are lengthy and very frequently invoked. So, for example, if the lock/unlock is around an `unordered_map`
251 * lookup with a quick hashing function, it would be quite difficult to induce enough lock contention
252 * to make a shared mutex better than an exclusive one. (Note this is assuming even no perf issue with
253 * `boost::shared_mutex` specifically.)
254 */
255using Mutex_shared_non_recursive = boost::shared_mutex;
256
257/**
258 * Short-hand for a mutex type equivalent to util::Mutex_shared_non_recursive -- except that the lock/unlock mutex ops
259 * all do nothing. One can parameterize templates accordingly; so that an algorithm can be generically written to work
260 * in both single- and multi-threaded contexts without branching into 2 code paths, yet avoid the unnecessary actual
261 * locking in the former case.
262 */
263using Mutex_noop_shared_non_recursive = boost::null_mutex;
264
265/**
266 * Short-hand for advanced-capability RAII lock guard for any mutex, ensuring exclusive ownership of that mutex.
267 * Note the advanced API available for the underlying type: it is possible to relinquish ownership without unlocking,
268 * gain ownership of a locked mutex; and so on.
269 *
270 * @see To grab shared-level ownership of a shared-or-exclusive mutex: use #Shared_lock_guard.
271 *
272 * @tparam Mutex
273 * A non-recursive or recursive mutex type. Recommend one of:
274 * #Mutex_non_recursive, #Mutex_recursive, #Mutex_shared_non_recursive, #Mutex_noop_shared_non_recursive.
275 */
276template<typename Mutex>
277using Lock_guard = boost::unique_lock<Mutex>;
278
279/**
280 * Short-hand for *shared mode* advanced-capability RAII lock guard, particuarly for #Mutex_shared_non_recursive
281 * mutexes.
282 *
283 * @tparam Shared_mutex
284 * Typically #Mutex_shared_non_recursive, but any mutex type with that both-exclusive-and-shared API will work.
285 */
286template<typename Shared_mutex>
287using Shared_lock_guard = boost::shared_lock<Shared_mutex>;
288
289/**
290 * (Deprecated given C++1x) Short-hand for advanced-capability RAII lock guard for #Mutex_non_recursive mutexes.
291 *
292 * @todo #Lock_guard_non_recursive is deprecated, now that C++1x made the more flexible
293 * `Lock_guard<Mutex_non_recursive>` possible. Remove it and all (outside) uses eventually.
294 */
295using Lock_guard_non_recursive = boost::unique_lock<Mutex_non_recursive>;
296
297/**
298 * (Deprecated given C++1x) Short-hand for advanced-capability RAII lock guard for #Mutex_recursive mutexes.
299 *
300 * @todo #Lock_guard_recursive is deprecated, now that C++1x made the more flexible `Lock_guard<Mutex_recursive>`
301 * possible. Remove it and all (outside) uses eventually.
302 */
303using Lock_guard_recursive = boost::unique_lock<Mutex_recursive>;
304
305/**
306 * (Deprecated given C++1x) Short-hand for *shared mode* advanced-capability RAII lock guard for
307 * #Mutex_shared_non_recursive mutexes.
308 *
309 * @todo #Lock_guard_shared_non_recursive_sh is deprecated, now that C++1x made the more flexible
310 * `Shared_lock_guard<Mutex_shared_non_recursive>` possible. Remove it and all (outside) uses eventually.
311 */
312using Lock_guard_shared_non_recursive_sh = boost::shared_lock<Mutex_shared_non_recursive>;
313
314/**
315 * (Deprecated given C++1x) Short-hand for *exclusive mode* advanced-capability RAII lock guard for
316 * #Mutex_shared_non_recursive mutexes.
317 *
318 * @todo #Lock_guard_shared_non_recursive_ex is deprecated, now that C++1x made the more flexible
319 * `Lock_guard<Mutex_shared_non_recursive>` possible. Remove it and all (outside) uses eventually.
320 */
321using Lock_guard_shared_non_recursive_ex = boost::unique_lock<Mutex_shared_non_recursive>;
322
323/**
324 * (Deprecated given C++1x) Equivalent to #Lock_guard_shared_non_recursive_sh but applied to
325 * #Mutex_noop_shared_non_recursive.
326 *
327 * @todo #Lock_guard_noop_shared_non_recursive_sh is deprecated, now that C++1x made the more flexible
328 * `Shared_lock_guard<Mutex_noop_shared_non_recursive>` possible. Remove it and all (outside) uses eventually.
329 */
330using Lock_guard_noop_shared_non_recursive_sh = boost::shared_lock<Mutex_noop_shared_non_recursive>;
331
332/**
333 * (Deprecated given C++1x) Equivalent to #Lock_guard_shared_non_recursive_ex but applied to
334 * #Mutex_noop_shared_non_recursive.
335 *
336 * @todo #Lock_guard_noop_shared_non_recursive_ex is deprecated, now that C++1x made the more flexible
337 * `Lock_guard<Mutex_noop_shared_non_recursive>` possible. Remove it and all (outside) uses eventually.
338 */
339using Lock_guard_noop_shared_non_recursive_ex = boost::unique_lock<Mutex_noop_shared_non_recursive>;
340
341/**
342 * Short-hand for `std::span`-like type; that is contiguous sequence of objects with the first element of the sequence
343 * at position zero.
344 *
345 * @todo Once we switch to C++20 (from C++17), #Span can be pointed at `std::span` instead of `boost::span`.
346 *
347 * @tparam T
348 * Element type.
349 * @tparam E
350 * Compile-time constant length of a span of this type; or `DYNAMIC_EXTENT` for it to be variable.
351 */
352template<typename T, size_t E = DYNAMIC_EXTENT>
353using Span = boost::span<T, E>;
354
355// Free functions.
356
357/**
358 * Equivalent to `val1.swap(val2)`.
359 *
360 * @relatesalso Linked_hash_map
361 * @param val1
362 * Object.
363 * @param val2
364 * Object.
365 */
366template<typename Key_t, typename Mapped_t, typename Hash_t, typename Pred_t>
369
370/**
371 * Equivalent to `val1.swap(val2)`.
372 *
373 * @relatesalso Linked_hash_set
374 * @param val1
375 * Object.
376 * @param val2
377 * Object.
378 */
379template<typename Key_t, typename Hash_t, typename Pred_t>
382
383/**
384 * Get the current POSIX (Unix) time as a duration from the Epoch time point.
385 *
386 * This is the amount of time -- according to the user-settable system clock time -- to have passed since the
387 * POSIX (Unix) Epoch -- January 1st, 1970, 00:00:00 UTC -- not counting leap seconds to have been inserted or deleted
388 * between then and now.
389 *
390 * The `boost::chrono` duration type is chosen so as to support the entire supported resolution of the
391 * OS-exposed system clock (but probably no more than that).
392 *
393 * ### Known use cases, alternatives ###
394 * - Logging of time stamps. Output the raw value; or use boost.locale to output `ceil<seconds>()` in the desired
395 * human-friendly form, splicing in the left-over microseconds where desired (boost.locale lacks formatters for
396 * sub-second-resolution time points). However see below for a typically-superior alternative.
397 * - By subtracting return values of this at various points in time from each other, as a crude timing mechanism.
398 * (Various considerations make it just that -- crude -- and best replaced by flow::Fine_clock and the like.
399 * Moreover see flow::perf::Checkpointing_timer.)
400 * - It's a decent quick-and-dirty random seed.
401 *
402 * ### Update/subtleties re. time stamp output ###
403 * Using this for time stamp output is no longer needed or convenient, as a much nicer way presents itself
404 * when combined with boost.chrono I/O-v2 `time_point`-outputting `ostream<<` overload. Just grab `time_point`
405 * `boost::chrono::system_clock::now()` (or another `system_clock`-originated value); its default-formatted
406 * `ostream<<` output will include date, time with microsecond+ precision, and time-zone specifier (one can choose
407 * UTC or local time).
408 *
409 * However, as of this writing, it is not possible to directly obtain *just* the microsecond+
410 * part of this, in isolation, according boost.chrono docs. (One could hack it by taking a substring.)
411 * Quote: "Unfortunately there are no formatting/parsing sequences which indicate fractional seconds." From:
412 * https://www.boost.org/doc/libs/1_76_0/doc/html/chrono/users_guide.html#chrono.users_guide.tutorial.i_o.system_clock_time_point_io)
413 *
414 * @return A duration representing how much time has passed since the Epoch reference point
415 * (could be negative if before it).
416 */
417boost::chrono::microseconds time_since_posix_epoch();
418
419/**
420 * Writes a multi- or single-line string representation of the provided binary data to an output stream, complete with
421 * a printable and hex versions of each byte.
422 * - Single-line mode is chosen by setting `bytes_per_line` to special value `-1`. In this mode, the output
423 * consists of `indentation`, followed by a pretty-printed hex dump of every byte in `data` (no matter how many),
424 * followed by a pretty-printed ASCII-printable (or '.' if not so printable) character for each byte; that's it.
425 * No newline is added, and `indentation` is included only the one time. It is recommended to therefore print
426 * "in-line" inside log messages (etc.) without surrounding newlines, etc., when using this mode.
427 * - Multi-line mode is chosen by setting `bytes_per_line` to a positive value; or 0 which auto-selects a decent
428 * default positive value. Then, each line represents up to that many bytes, which are pretty-printed similarly
429 * to single-line mode, in order of appearance in `data` (with the last such line representing the last few bytes,
430 * formatting nicely including accounting for potentially fewer than the desired # of bytes per line).
431 * Every line starts with `indentation` and ends with a newline -- including the last line.
432 * Therefore, it is recommended to precede this call with an output of a newline and to avoid doing so
433 * after that call (unless blank line is desired).
434 *
435 * Example with a single contiguous memory area, multi-line mode:
436 *
437 * ~~~
438 * array<uint8_t, 256 * 256> bytes(...);
439 *
440 * // Output to cout.
441 * cout
442 * << "Buffer contents: [\n";
443 * buffers_to_ostream(cout,
444 * boost::asio::buffer(bytes), // Turn a single memory array into a buffer sequence.
445 * " ");
446 * << "]."; // This will be on its own line at the end.
447 * ~~~
448 *
449 * See also buffers_dump_string() which returns a string and can thus be more easily used directly inside
450 * FLOW_LOG_DATA() and similar log macros.
451 *
452 * ### Performance ###
453 * This thing is slow... it's not trying to be fast and can't be all that fast anyway. As usual, though, if used
454 * in FLOW_LOG_DATA() (etc.) its slowness will only come into play if the log filter passes which (esp. for
455 * log::Severity::S_DATA) it usually won't.
456 *
457 * That said buffers_dump_string() is even slower, because it'll use an intermediate `ostream` independent of whatever
458 * `ostream` you may or may not be placing the resulting string. However it's easier to use with `FLOW_LOG_...()`,
459 * and since in that case perf is typically not an issue, it makes sense to use the easier thing typically.
460 *
461 * However, if you do want to avoid that extra copy and need to *also* use buffers_to_ostream() directly inside
462 * `FLOW_LOG_...()` then the following technique isn't too wordy and works:
463 *
464 * ~~~
465 * const array<uint8_t, 256 * 256> bytes(...);
466 *
467 * // Log with a flow::log macro.
468 * const flow::Function<ostream& (ostream&)> os_manip = [&](ostream& os) -> ostream&
469 * {
470 * return buffers_to_ostream(os, boost::asio::buffer(bytes), " ");
471 * };
472 * FLOW_LOG_INFO("Buffer contents: [\n" << os_manip << "].");
473 *
474 * // Above is probably more performant than:
475 * FLOW_LOG_INFO("Buffer contents: [\n"
476 * << buffers_dump_string(boost::asio::buffer(bytes), " ") // Intermediate+copy, slow....
477 * << "].");
478 * // flow::util::ostream_op_string() is a bit of an improvement but still. :-)
479 * ~~~
480 *
481 * ### Rationale ###
482 * The reason it returns `os` and takes a reference-to-mutable instead of the customary (for this project's
483 * style, to indicate modification potential at call sites) pointer-to-mutable is in order to be `bind()`able
484 * in such a way as to make an `ostream` manipulator. In the example above we use a lambda instead of `bind()`
485 * however.
486 *
487 * @tparam Const_buffer_sequence
488 * Type that models the boost.asio `ConstBufferSequence` concept (see Boost docs) which represents
489 * 1 or more scattered buffers in memory (only 1 buffer in a sequence is common).
490 * In particular `boost::asio::const_buffer` works when dumping a single buffer.
491 * @param os
492 * The output stream to which to write.
493 * @param data
494 * The data to write, given as an immutable sequence of buffers each of which is essentially a pointer
495 * and length. (Reminder: it is trivial to make such an object from a single buffer as well;
496 * for example given `array<uint8_t, 256> data` (an array of 256 bytes), you can just pass
497 * `boost::asio::buffer(data)`, as the latter returns an object whose type satisfies requirements of
498 * `Const_buffer_sequence` despite the original memory area being nothing more than a single
499 * byte array.)
500 * @param indentation
501 * The indentation to use at the start of every line of output.
502 * @param bytes_per_line
503 * If 0, act as-if a certain default positive value were passed; and then: If `-1`, single-line mode is invoked.
504 * If a positive value, multi-line mode is invoked, with all lines but the last one consisting of
505 * a dump of that many contiguous bytes of `data`. (Yes, multi-line mode is still in force, even if there
506 * are only enough bytes in `data` for one line of output anyway.)
507 * @return `os`.
508 */
509template<typename Const_buffer_sequence>
510std::ostream& buffers_to_ostream(std::ostream& os, const Const_buffer_sequence& data, const std::string& indentation,
511 size_t bytes_per_line = 0);
512
513/**
514 * Identical to buffers_to_ostream() but returns an `std::string` instead of writing to a given `ostream`.
515 *
516 * @see buffers_to_ostream() doc header for notes on performance and usability.
517 *
518 * @tparam Const_buffer_sequence
519 * See buffers_to_ostream().
520 * @param data
521 * See buffers_to_ostream().
522 * @param indentation
523 * See buffers_to_ostream().
524 * @param bytes_per_line
525 * See buffers_to_ostream().
526 * @return Result string.
527 */
528template<typename Const_buffer_sequence>
529std::string buffers_dump_string(const Const_buffer_sequence& data, const std::string& indentation,
530 size_t bytes_per_line = 0);
531
532/**
533 * Utility that converts a bandwidth in arbitrary units in both numerator and denominator to the same bandwidth
534 * in megabits per second. The input bandwidth is given in "items" per `Time_unit{1}`; where `Time_unit` is an
535 * arbitrary boost.chrono `duration` type that must be explicitly provided as input; and an "item" is defined
536 * as `bits_per_item` bits. Useful at least for logging. It's probably easiest to understand by example; see below;
537 * rather than by parsing that description I just wrote.
538 *
539 * To be clear (as C++ syntax is not super-expressive in this case) -- the template parameter `Time_unit` is
540 * an explicit input to the function template, essentially instructing it as to in what units `items_per_time` is.
541 * Thus all uses of this function should look similar to:
542 *
543 * ~~~
544 * // These are all equal doubles, because the (value, unit represented by value) pair is logically same in each case.
545 *
546 * // We'll repeatedly convert from 2400 mebibytes (1024 * 1024 bytes) per second, represented one way or another.
547 * const size_t MB_PER_SEC = 2400;
548 *
549 * // First give it as _mebibytes_ (2nd arg) per _second_ (template arg).
550 * const double mbps_from_mb_per_sec
551 * = flow::util::to_mbit_per_sec<chrono::seconds>(MB_PER_SEC, 1024 * 8);
552 *
553 * // Now give it as _bytes_ (2nd arg omitted in favor of very common default = 8) per _second_ (template arg).
554 * const double mbps_from_b_per_sec
555 * = flow::util::to_mbit_per_sec<chrono::seconds>(MB_PER_SEC * 1024 * 1024);
556 *
557 * // Now in _bytes_ per _hour_.
558 * const double mbps_from_b_per_hour
559 * = flow::util::to_mbit_per_sec<chrono::hours>(MB_PER_SEC * 1024 * 1024 * 60 * 60);
560 *
561 * // Finally give it in _bytes_ per _1/30th-of-a-second_ (i.e., per frame, when the frame rate is 30fps).
562 * const double mbps_from_b_per_30fps_frame
563 * = flow::util::to_mbit_per_sec<chrono::duration<int, ratio<1, 30>>(MB_PER_SEC * 1024 * 1024 / 30);
564 * ~~~
565 *
566 * @note Megabit (1000 x 1000 = 10^6 bits) =/= mebibit (1024 x 1024 = 2^20 bits); but the latter is only about 5% more.
567 * @todo boost.unit "feels" like it would do this for us in some amazingly pithy and just-as-fast way. Because Boost.
568 * @tparam Time_unit
569 * `boost::chrono::duration<Rep, Period>` for some specific `Rep` and `Period`.
570 * See `boost::chrono::duration` documentation.
571 * Example types: `boost::chrono::milliseconds`; `boost::chrono::seconds`; see example use code above.
572 * @tparam N_items
573 * Some (not necessarily integral) numeric type. Strictly speaking, any type convertible to `double` works.
574 * @param items_per_time
575 * The value, in items per `Time_unit{1}` (where there are `bits_per_item` bits in 1 item) to convert to
576 * megabits per second. Note this need not be an integer.
577 * @param bits_per_item
578 * Number of bits in an item, where `items_per_time` is given as a number of items.
579 * @return See above.
580 */
581template<typename Time_unit, typename N_items>
582double to_mbit_per_sec(N_items items_per_time, size_t bits_per_item = 8);
583
584/**
585 * Returns the result of the given non-negative integer divided by a positive integer, rounded up to the nearest
586 * integer. Internally, it avoids floating-point math for performance.
587 *
588 * @note `constexpr`: can be used in compile-time expressions.
589 * @see round_to_multiple() which is essentially `return b * ceil_div(a, b)`.
590 *
591 * @tparam Integer
592 * A signed or unsigned integral type.
593 * @tparam Integer2
594 * Ditto.
595 * @param dividend
596 * Dividend; non-negative (else results undefined).
597 * @param divisor
598 * Divisor; positive (else results undefined).
599 * @return Ceiling of `(dividend / divisor)`.
600 */
601template<typename Integer, typename Integer2>
602constexpr Integer ceil_div(Integer dividend, Integer2 divisor);
603
604/**
605 * Returns the smallest integer >= the given integer `dividend` such that it is a multiple
606 * of the given integer `unit`. Essentialy that is: `unit * ceil_div(dividend, unit)`.
607 *
608 * For example: 0 in 1024s => 0; 1 in 1024s => 1024; 1024 in 1024s => 1024; 1025 in 1024s => 2048.
609 *
610 * @note `constexpr`: can be used in compile-time expressions.
611 *
612 * @tparam Integer
613 * A signed or unsigned integral type.
614 * @tparam Integer2
615 * Ditto.
616 * @param dividend
617 * Dividend; non-negative (else results undefined).
618 * @param unit
619 * Divisor; positive (else results undefined).
620 * @return See above.
621 */
622template<typename Integer, typename Integer2>
623constexpr Integer round_to_multiple(Integer dividend, Integer2 unit);
624
625/**
626 * Provides a way to execute arbitrary (cleanup) code at the exit of the current block. Simply
627 * save the returned object into a local variable that will go out of scope when your code block
628 * exits. Example:
629 *
630 * ~~~
631 * {
632 * X* x = create_x();
633 * auto cleanup = util::setup_auto_cleanup([&]() { delete_x(x); });
634 * // Now delete_x(x) will be called no matter how the current { block } exits.
635 * // ...
636 * }
637 * ~~~
638 *
639 * @todo setup_auto_cleanup() should take a function via move semantics.
640 *
641 * @tparam Cleanup_func
642 * Any type such that given an instance `Cleanup_func f`, the expression `f()` is valid.
643 * @param func
644 * `func()` will be called when cleanup is needed.
645 * @return A light-weight object that, when it goes out of scope, will cause `func()` to be called.
646 */
647template<typename Cleanup_func>
648Auto_cleanup setup_auto_cleanup(const Cleanup_func& func);
649
650/**
651 * Returns `true` if and only if the given value is within the given range, inclusive.
652 *
653 * @param min_val
654 * Lower part of the range.
655 * @param val
656 * Value to check.
657 * @param max_val
658 * Higher part of the range. Must be greater than or equal to `min_val`, or behavior is undefined.
659 * @tparam T
660 * A type for which the operation `x < y` is defined and makes sense. Examples: `double`, `char`,
661 * `unsigned int`, #Fine_duration.
662 * @return `true` if and only if `val` is in [`min_val`, `max_val`].
663 */
664template<typename T>
665bool in_closed_range(T const & min_val, T const & val, T const & max_val);
666
667/**
668 * Returns `true` if and only if the given value is within the given range, given as a [low, high)
669 * pair.
670 *
671 * @param min_val
672 * Lower part of the range.
673 * @param val
674 * Value to check.
675 * @param max_val
676 * Higher part of the range. Must be greater than `min_val`, or behavior is undefined.
677 * @tparam T
678 * A type for which the operation `x < y` is defined and makes sense. Examples: `double`, `char`,
679 * `unsigned int`, #Fine_duration.
680 * @return `true` if and only if `val` is in [`min_val`, `max_val`), i.e., `min_val` <= `val` < `max_val`.
681 */
682template<typename T>
683bool in_closed_open_range(T const & min_val, T const & val, T const & max_val);
684
685/**
686 * Returns `true` if and only if the given value is within the given range, given as a (low, high]
687 * pair.
688 *
689 * @param min_val
690 * Lower part of the range.
691 * @param val
692 * Value to check.
693 * @param max_val
694 * Higher part of the range. Must be greater than `min_val`, or behavior is undefined.
695 * @tparam T
696 * A type for which the operation `x < y` is defined and makes sense. Examples: `double`, `char`,
697 * `unsigned int`, #Fine_duration.
698 * @return `true` if and only if `val` is in (`min_val`, `max_val`], i.e., `min_val` < `val` <= `max_val`.
699 */
700template<typename T>
701bool in_open_closed_range(T const & min_val, T const & val, T const & max_val);
702
703/**
704 * Returns `true` if and only if the given value is within the given range, given as a (low, high)
705 * pair.
706 *
707 * @param min_val
708 * Lower part of the range.
709 * @param val
710 * Value to check.
711 * @param max_val
712 * Higher part of the range. Must be at least 2 greater than `min_val`, or behavior is undefined.
713 * @tparam T
714 * A type for which the operation `x < y` is defined and makes sense. Examples: `double`, `char`,
715 * `unsigned int`, #Fine_duration.
716 * @return `true` if and only if `val` is in (`min_val`, `max_val`), i.e., `min_val` < `val` < `max_val`.
717 */
718template<typename T>
719bool in_open_open_range(T const & min_val, T const & val, T const & max_val);
720
721/**
722 * Returns `true` if and only if the given key is present at least once in the given associative
723 * container.
724 *
725 * @tparam Container
726 * Associative container type (`boost::unordered_map`, `std::set`, etc.).
727 * In particular must have the members `find()`, `end()`, and `key_type`.
728 * @param container
729 * Container to search.
730 * @param key
731 * Key to find.
732 * @return See above.
733 */
734template<typename Container>
735bool key_exists(const Container& container, const typename Container::key_type& key);
736
737/**
738 * Performs `*minuend -= subtrahend`, subject to a floor of `floor`. Avoids underflow/overflow to the extent
739 * it's reasonably possible, but no more. The return value indicates whether
740 * the floor was hit; this allows one to chain high-performance subtractions like this:
741 *
742 * ~~~
743 * double t = 44;
744 * int x = rnd(); // Suppose x == 123, for example.
745 * // Avoids the 2nd, 3rd computation altogether, as the first detects that x >= 44, and thus t == 0 regardless.
746 * subtract_with_floor(&t, x) &&
747 * subtract_with_floor(&t, long_computation()) &&
748 * subtract_with_floor(&t, another_long_computation());
749 * ~~~
750 *
751 * @tparam Minuend
752 * Numeric type.
753 * @tparam Subtrahend
754 * Numeric type, such that given `Subtrahend s`, `Minuend{s}` is something reasonable for all `s` involved.
755 * @param minuend
756 * `*minuend` is set to either `(*minuend - subtrahend)` or `floor`, whichever is higher.
757 * @param subtrahend
758 * Ditto.
759 * @param floor
760 * Ditto. Negatives are OK. Typically it's best to keep the magnitude of this small.
761 * @return `true` if `*minuend == floor` at function exit; `false` if `*minuend > floor`.
762 */
763template<typename Minuend, typename Subtrahend>
764bool subtract_with_floor(Minuend* minuend, const Subtrahend& subtrahend, const Minuend& floor = 0);
765
766/**
767 * Answers the question *what's the smallest integer number of `To`s sufficient to verbatim store the given number of
768 * `From`s?*, where `From` and `To` are POD types.
769 *
770 * For example, one needs 1 `uint64_t` to store 1, 2, 3, or 4 `uint16_t`s, hence
771 * `size_unit_convert<uint16_t, uint64_t>(1 or 2 or 3 or 4) == 1`. Similarly, 5 or 6 or 7 or 8 -> 2.
772 * It works in the opposite direction, too; if we are storing `uint64_t`s in multiples of `uint16_t`, then
773 * 1 -> 4, 2 -> 8, 3 -> 12, etc.
774 *
775 * To be clear, when `From` bit width is smaller than `To` bit width, some of the bits will be padding and
776 * presumably unused. For example, raw data buffers of arbitrary bytes are often arranged in multi-byte "words."
777 *
778 * @tparam From
779 * The POD type of the values that must be encoded in `From`s.
780 * @tparam To
781 * The POD type of the array that would store the `From`s.
782 * @param num_froms
783 * How many `From`s does one want to encode in an array of `To`s?
784 * @return How many `To`s are sufficient to encode `num_from` `From`s verbatim?
785 */
786template<typename From, typename To>
787size_t size_unit_convert(From num_froms);
788
789/**
790 * Given a generic sequence (integer -> object) generates a generic map (object -> integer) providing inverse
791 * lookup. See the 3-arg overload if you want to provide a more complex lookup function to store something else based
792 * on each index.
793 *
794 * A naive way of implementing lookups otherwise would be a linear search for the object; using this will
795 * use RAM to avoid the slow searches.
796 *
797 * @tparam Sequence
798 * Sequence such as `std::vector<T>` or `std::array<T>`.
799 * Informally, `T` should be something light-weight and hence usable as a key type for a map type (`Map`).
800 * @tparam Map
801 * Map that maps `T` from `Sequence` to `size_t`. Example: `std::map<T, size_t>`.
802 * @param src_seq
803 * Input sequence.
804 * @param target_map
805 * Output map. Note it will *not* be pre-cleared; informally, this means one can shove 2+ lookup maps
806 * into one. If null behavior undefined (assertion may trip).
807 */
808template<typename Map, typename Sequence>
809void sequence_to_inverted_lookup_map(Sequence const & src_seq, Map* target_map);
810
811/**
812 * Similar to the 2-arg overload of sequence_to_inverted_lookup_map() but with the ability to store a value based
813 * on the index into the input sequence instead of that index itself. See the 2-arg overload.
814 *
815 * @tparam Sequence
816 * Sequence such as `std::vector<T>` or `std::array<T>`.
817 * Informally, `T` should be something light-weight and hence usable as a key type for a map type (`Map`).
818 * @tparam Map
819 * Map that maps `T` from `Sequence` to another type `X`. Example:
820 * `unordered_map<T, X>`, where an `X` can be computed from a `size_t` index.
821 * @param src_seq
822 * See 2-arg overload.
823 * @param target_map
824 * See 2-arg overload.
825 * @param idx_to_map_val_func
826 * Given an index `idx` into `src_seq`, `(*target_map)[]` shall contain `idx_to_map_val_func(idx)`.
827 * Use this arg to instead perform a second lookup before storing a value in `*target_map`.
828 * Use the 2-arg overload if you'd like to store the index itself.
829 */
830template<typename Map, typename Sequence>
832 (Sequence const & src_seq, Map* target_map,
833 const Function<typename Map::mapped_type (size_t)>& idx_to_map_val_func);
834
835/**
836 * Writes to the specified string, as if the given arguments were each passed, via `<<` in sequence,
837 * to an `ostringstream`, and then the result were appended to the aforementioned string variable.
838 *
839 * Tip: It works nicely, 99% as nicely as simply `<<`ing an `ostream`; but certain language subtleties mean
840 * you may have to fully qualify some template instances among `ostream_args`. Do so if you receive a
841 * "deduced incomplete pack" (clang) or similar error, as I have seen when using, e.g., `chrono::symbol_format`
842 * formatter (which the compile error forced me to qualify as: `symbol_format<char, ostream::traits_type>`).
843 *
844 * @see log::Thread_local_string_appender for an even more efficient version of this for some applications that can
845 * also enable a continuous stream across multiple stream-writing statements over time.
846 *
847 * @tparam T
848 * Each type `T` is such that `os << t`, with types `T const & t` and `ostream& os`, builds and writes
849 * `t` to `os`, returning lvalue `os`.
850 * Usually in practice this means the existence of `ostream& operator<<(ostream&, T const &)` or
851 * `ostream& operator<<(ostream&, T)` overload, the latter usually for basic types `T`.
852 * See also tip above, if compiler is unable to deduce a given `T` (even when it *would* deduce it
853 * in `os << t`).
854 * @param target_str
855 * Pointer to the string to which to append.
856 * @param ostream_args
857 * One or more arguments, such that each argument `arg` is suitable for `os << arg`, where
858 * `os` is an `ostream`.
859 */
860template<typename... T>
861void ostream_op_to_string(std::string* target_str, T&&... ostream_args);
862
863/**
864 * Equivalent to ostream_op_to_string() but returns a new `string` by value instead of writing to the caller's
865 * `string`. This is useful at least in constructor initializers, where it is not possible to first
866 * declare a stack variable.
867 *
868 * With the C++11-y use of move semantics in STL it should be no slower than using
869 * `ostream_op_to_string()` -- meaning, it is no slower, period, as this library now requires C++11.
870 *
871 * @tparam T
872 * See ostream_op_to_string().
873 * @param ostream_args
874 * See ostream_op_to_string().
875 * @return Resulting `std::string`.
876 */
877template<typename... T>
878std::string ostream_op_string(T&&... ostream_args);
879
880/**
881 * Function template that simply outputs arguments 2+ via `<<` to the given `ostream`, in the order given.
882 *
883 * @tparam T
884 * See `T` in ostream_op_to_string().
885 * @param ostream_args
886 * See `ostream_args` in ostream_op_to_string().
887 * @param os
888 * Pointer to stream to which to sequentially send arguments for output.
889 */
890template<typename... T>
891void feed_args_to_ostream(std::ostream* os, T&&... ostream_args);
892
893/**
894 * Deserializes an `enum class` value from a standard input stream. Reads up to but not including the next
895 * non-alphanumeric-or-underscore character; the resulting string is then mapped to an `Enum`. If none is
896 * recognized, `enum_default` is the result. The recognized values are:
897 * - "0", "1", ...: Corresponds to the underlying-integer conversion to that `Enum`. (Can be disabled optionally.)
898 * - Case-[in]sensitive string encoding of the `Enum`, as determined by `operator<<(ostream&)` -- which must exist
899 * (or this will not compile). Informally we recommend the encoding to be the non-S_-prefix part of the actual
900 * `Enum` member; e.g., `"WARNING"` for log::Sev::S_WARNING.
901 * If the scanned token does not map to any of these, or if end-of-input is encountered immediately (empty token),
902 * then `enum_default` is returned.
903 *
904 * Error semantics: There are no invalid values or exceptions thrown; `enum_default` returned is the worst case.
905 * Do note `*is_ptr` may not be `good() == true` after return.
906 *
907 * Tip: It is convenient to implement `operator>>(istream&)` in terms of istream_to_enum(). With both
908 * `>>` and `<<` available, serialization/deserialization of the `enum class` will work; this enables a few key things
909 * to work, including parsing from config file/command line via and conversion from `string` via `lexical_cast`.
910 *
911 * Informal convention suggestion: `S_END_SENTINEL` should be the sentinel member of `Enum`. E.g., see log::Sev.
912 *
913 * @tparam Enum
914 * An `enum class` which must satisfy the following requirements or else risk undefined behavior (if it
915 * compiles): An element, `enum_lowest`, has a non-negative integer value.
916 * Subsequent elements are strictly monotonically increasing with increment 1, up to and including
917 * `enum_sentinel`. (Elements outside [`enum_lowest`, `enum_sentinel`] may exist, as long as their numeric
918 * values don't conflict with those in-range, but informally we recommend against this.)
919 * `ostream << Enum` exists and works without throwing for all values in range
920 * [`enum_lowest`, `enum_sentinel`). Each `<<`-serialized string must be distinct from the others.
921 * Each `<<`-serialized string must start with a non-digit and must consist only of alphanumerics and
922 * underscores. Exception: digit-leading is allowed if and only if `!accept_num_encoding`, though
923 * informally we recommend against it as a convention.
924 *
925 * @param is_ptr
926 * Stream from which to deserialize.
927 * @param enum_default
928 * Value to return if the token does not match either the numeric encoding (if enabled) or the `<<` encoding.
929 * `enum_sentinel` is a sensible (but not the only sensible) choice.
930 * @param enum_sentinel
931 * `Enum` value such that all valid deserializable values have numeric conversions strictly lower than it.
932 * @param accept_num_encoding
933 * If `true`, a numeric value is accepted as an encoding; otherwise it is not (and will yield `enum_default`
934 * like any other non-matching token).
935 * @param case_sensitive
936 * If `true`, then the token must exactly equal an `ostream<<` encoding of a non-sentinel `Enum`;
937 * otherwise it may equal it modulo different case.
938 * @param enum_lowest
939 * The lowest `Enum` value. Its integer value is very often 0, sometimes 1.
940 * Behavior undefined if it is negative.
941 * @return See above.
942 */
943template<typename Enum>
944Enum istream_to_enum(std::istream* is_ptr, Enum enum_default, Enum enum_sentinel,
945 bool accept_num_encoding = true, bool case_sensitive = false,
946 Enum enum_lowest = Enum(0));
947
948/**
949 * Sets certain `chrono`-related formatting on the given `ostream` that results in a consistent, desirable output
950 * of `duration`s and certain types of `time_point`s. As of this writing this includes enabling short unit format
951 * (e.g., "ms" instead of "milliseconds") and avoiding Unicode characters (the Greek letter for micro becomes
952 * a similar-looking "u" instead).
953 *
954 * @see log::beautify_chrono_logger_this_thread() to affect a Logger directly.
955 * @see flow::async in which new threads are set to use this formatting automatically. However you'll want to
956 * do this explicitly for the startup thread.
957 *
958 * @param os
959 * The stream to affect.
960 */
961void beautify_chrono_ostream(std::ostream* os);
962
963/**
964 * Estimate of memory footprint of the given value, including memory allocated on its behalf -- but
965 * excluding its shallow `sizeof`! -- in bytes.
966 *
967 * @param val
968 * Value.
969 * @return See above.
970 */
971size_t deep_size(const std::string& val);
972
973/**
974 * Serializes a Thread_local_state_registry to a standard output stream.
975 *
976 * @relatesalso Thread_local_state_registry
977 *
978 * @param os
979 * Stream to which to serialize.
980 * @param val
981 * Value to serialize.
982 * @return `os`.
983 */
984template<typename Thread_local_state_t>
985std::ostream& operator<<(std::ostream& os, const Thread_local_state_registry<Thread_local_state_t>& val);
986
987// Macros.
988
989/**
990 * Expands to an `ostream` fragment `X` (suitable for, for example: `std::cout << X << ": Hi!"`) containing
991 * the file name, function name, and line number at the macro invocation's context.
992 *
993 * It's a functional macro despite taking no arguments to convey that it mimics a free function sans args.
994 *
995 * @internal
996 *
997 * ### Performance ###
998 * The items `<<`ed onto the target `ostream` are each evaluated at compile-time.
999 * This includes the expression involving flow::util::get_last_path_segment() which is `constexpr`.
1000 */
1001#define FLOW_UTIL_WHERE_AM_I() \
1002 FLOW_UTIL_WHERE_AM_I_FROM_ARGS(::flow::util::get_last_path_segment \
1003 (::flow::util::String_view(__FILE__, sizeof(__FILE__) - 1)), \
1004 ::flow::util::String_view(__FUNCTION__, sizeof(__FUNCTION__) - 1), \
1005 __LINE__)
1006
1007/**
1008 * Same as FLOW_UTIL_WHERE_AM_I() but evaluates to an `std::string`. It's probably a bit slower as
1009 * well. Update: In fact, it's probably significantly slower as of this writing, as
1010 * FLOW_UTIL_WHERE_AM_I() evaluates the `<<`ed items at compile-time, while this cannot due to how it's implemented.
1011 *
1012 * @internal
1013 *
1014 * flow::util::get_where_am_i_str() is too clever to become a `constexpr` function, even if it were radically rewritten,
1015 * so this macro evaluates to a partially runtime-computed expression. Hence the note just above about perf.
1016 *
1017 * @todo See if FLOW_UTIL_WHERE_AM_I_STR() can be coaxed into a compile-time expression after all. It is used in
1018 * quite a lot of frequently executed code, namely at the top of most Flow (and Flow-like) APIs that can emit errors.
1019 * See notes inside flow::util::get_where_am_i_str() on this as of this writing.
1020 */
1021#define FLOW_UTIL_WHERE_AM_I_STR() \
1022 ::flow::util::get_where_am_i_str(::flow::util::get_last_path_segment \
1023 (::flow::util::String_view(__FILE__, sizeof(__FILE__) - 1)), \
1024 ::flow::util::String_view(__FUNCTION__, sizeof(__FUNCTION__) - 1), \
1025 __LINE__)
1026
1027/**
1028 * Use this to create a semicolon-safe version of a "void" functional macro definition consisting of at least two
1029 * statements; or of one statement that would become two statements by appending a semicolon.
1030 *
1031 * There may be other use cases where it might be useful, though none more has come to mind as of this writing.
1032 * Loosely speaking, IF your sub-statements are always blocks, and you have a "void" functional macro to be used in
1033 * the typical way (every use is a statement that looks like a function call), and the macro's definition is anything
1034 * *other* than an expression with an intentionally missing trailing semicolon, THEN you should probably wrap
1035 * that would-be macro definition in a FLOW_UTIL_SEMICOLON_SAFE(). However, read on if you want to know rationale
1036 * and/or formalities.
1037 *
1038 * ### Formal use case requirements ###
1039 * The following is assumed about every *use* of this macro; behavior is undefined otherwise.
1040 *
1041 * - The macro's invocation is the *entire definition* of another macro, M.
1042 * - M is a functional macro taking 0 or more arguments (possibly variadic).
1043 * - The following is true about every *use* of the macro M:
1044 * - The invocation is written as if M is a free function in the C language, and it is being "called"
1045 * as the *entirety* of the statement containing that "call." That is, it must look like this:
1046 *
1047 * ~~~
1048 * M(...arg 1 value..., ...arg 2 value..., ...more...); // (Or however many args M actually allows.)
1049 * ~~~
1050 *
1051 * ### Known use case 1: Macro definition is 2+ statements ###
1052 * Suppose your macro's value is a series of two or more statements executing in series without braces `{}`
1053 * around the whole thing. Then, in some contexts, invoking that macro as intended might result in
1054 * unexpected runtime misbehavior that the compiler wouldn't detect. A simple example with two
1055 * expressions as individual statements:
1056 *
1057 * ~~~
1058 * #define DOUBLE_AND_PRINT(arg) \
1059 * arg *= 2; // Statement 1. \
1060 * cout << arg // Statement 2. Note the lacking trailing semicolon (invoker must supply it after "call"). \
1061 * DOUBLE_AND_PRINT(x); // No problem. Both statements execute.
1062 * if (some_flag)
1063 * DOUBLE_AND_PRINT(x); // UNINTENDED BEHAVIOR! Statement 2 executes regardless of some_flag!
1064 * ~~~
1065 *
1066 * Granted, if the invoker used braces appropriately around the `if` statement body, there'd be no issue, but one
1067 * cannot always rely on invoker's good style, especially if the macro is part of a public library API.
1068 * Solution:
1069 *
1070 * ~~~
1071 * #define DOUBLE_AND_PRINT(arg) \
1072 * FLOW_UTIL_SEMICOLON_SAFE \
1073 * ( \
1074 * arg *= 2; // Statement 1. \
1075 * cout << arg; // Statement 2. Note necessity for trailing semicolon. \
1076 * )
1077 * DOUBLE_AND_PRINT(x); // No problem. Both statements execute.
1078 * if (some_flag)
1079 * DOUBLE_AND_PRINT(x); // No problem. Both statements execute; or neither one does.
1080 * ~~~
1081 *
1082 * One might ask: Why not simply surround the 2+ statements with braces `{}` to eliminate the problem more simply?
1083 * Answer: This actually would turn the use case into the following other problematic use case.
1084 *
1085 * ### Known use case 2: Required semicolon `;` trailing macro invocation leads to syntax error ###
1086 * Recall that the premise *requires* invoker to call your macro M like `M();`, meaning they will *always* put
1087 * a semicolon after the invocation. Now suppose that doing so will turn one statement (which is M's definition)
1088 * into two. Another way of putting it: Suppose M's body is already a complete statement, even without the required
1089 * trailing `;` (and there is no way to make it otherwise; usually [always?] because it ends with a `}`).
1090 * Then in some contexts it'll cause a syntax error. Example:
1091 *
1092 * ~~~
1093 * #define CHECK_AND_LOG(msg) \
1094 * if (filter()) \
1095 * { \
1096 * log(msg); \
1097 * } // Semicolon will always be added right here.
1098 * CHECK_AND_LOG("Hello."); // No problem. The empty ; statement introduced is harmless.
1099 * if (terminating)
1100 * CHECK_AND_LOG(msg); // SYNTAX ERROR! The empty ; will make the `else` illegal.
1101 * else
1102 * exit();
1103 * ~~~
1104 *
1105 * Removing the `;` from the invocation is no solution. Firstly it'll confuse many editors that will think the
1106 * "function call" (really macro invocation) is missing the usual semicolon. This might cause incorrect
1107 * auto-indentation in the file and who knows what else. Code analyzer tools may also be affected.
1108 * Even ignoring issues where the code is fed into a non-compiler, there are possible flow control problems.
1109 * In this example it'll attach the `else` in the invoking code to the inner `if` (from the macro)
1110 * instead of the outer `if` (in the invoking code) as intended. Wrapping the body of `CHECK_AND_LOG()` in
1111 * the proposed wrapper will resolve all stated problems. (Solution code omitted for brevity and obviousness
1112 * at this point.)
1113 *
1114 * @note Adding this wrapper would slightly adversely affect performance in the complete absence of compiler
1115 * optimization, but even the most basic optimizer (one capable of eliminating `if (false)` and similar)
1116 * should entirely eliminate any such performance degradation.
1117 *
1118 * @param ARG_func_macro_definition
1119 * The intended value of a functional macro, such that the "function" it approximates would have
1120 * return type `void`. Behavior is undefined if the value of this parameter ends in a semicolon, or
1121 * if the value contains a statement that includes another statement within it that is not a block
1122 * (`{ ... }`). (The rules in the last [English] statement may or may not be strictly necessary,
1123 * but requiring these allows me to generalize/reason more straightforwardly. In any case, one rule is
1124 * assumed good style anyway, while the other is simply practical in this context.)
1125 * @return Code to be used as the entire definition of a macro whose definition would have been
1126 * `ARG_func_macro_definition` if not for the resulting compile error or unexpected flow control
1127 * effects detailed above.
1128 */
1129#define FLOW_UTIL_SEMICOLON_SAFE(ARG_func_macro_definition) \
1130 do \
1131 { \
1132 ARG_func_macro_definition \
1133 } \
1134 while (false)
1135
1136} // namespace flow::util
An object of this class is a map that combines the lookup speed of an unordered_map<> and ordering an...
An object of this class is a map that combines the lookup speed of an unordered_set<> and ordering an...
An empty interface, consisting of nothing but a default virtual destructor, intended as a boiler-plat...
Definition: util.hpp:46
Optional-use companion to Thread_local_state_registry that enables the Polled_share_state pattern whe...
Definition: thread_lcl.hpp:818
Base class for Rnd_gen_uniform_range and Rnd_gen_uniform_range_mt for various aliases and similar,...
Definition: random.hpp:33
Identical to Rnd_gen_uniform_range but safe for concurrent RNG given a single object.
Definition: random.hpp:158
Simple, non-thread-safe uniform-range random number generator.
Definition: random.hpp:104
A simple RAII-pattern class template that, at construction, sets the specified location in memory to ...
Definition: util.hpp:146
Convenience class template that endows the given subclass T with nested aliases Ptr and Const_ptr ali...
Similar to ostringstream but allows fast read-only access directly into the std::string being written...
Similar to boost::thread_specific_ptr<T> but with built-in lazy-init semantics; and more importantly ...
Definition: thread_lcl.hpp:145
Each object of this class stores (at construction) and returns (on demand) a numeric ID unique from a...
Flow module containing miscellaneous general-use facilities that don't fit into any other Flow module...
Definition: basic_blob.hpp:31
boost::unique_lock< Mutex_recursive > Lock_guard_recursive
(Deprecated given C++1x) Short-hand for advanced-capability RAII lock guard for Mutex_recursive mutex...
Definition: util_fwd.hpp:303
bool in_closed_open_range(T const &min_val, T const &val, T const &max_val)
Returns true if and only if the given value is within the given range, given as a [low,...
Definition: util.hpp:296
bool key_exists(const Container &container, const typename Container::key_type &key)
Returns true if and only if the given key is present at least once in the given associative container...
Definition: util.hpp:310
void beautify_chrono_ostream(std::ostream *os_ptr)
Sets certain chrono-related formatting on the given ostream that results in a consistent,...
Definition: util.cpp:173
Auto_cleanup setup_auto_cleanup(const Cleanup_func &func)
Provides a way to execute arbitrary (cleanup) code at the exit of the current block.
Definition: util.hpp:316
Thread::id Thread_id
Short-hand for an OS-provided ID of a util::Thread.
Definition: util_fwd.hpp:102
void sequence_to_inverted_lookup_map(Sequence const &src_seq, Map *target_map, const Function< typename Map::mapped_type(size_t)> &idx_to_map_val_func)
Similar to the 2-arg overload of sequence_to_inverted_lookup_map() but with the ability to store a va...
Definition: util.hpp:392
double to_mbit_per_sec(N_items items_per_time, size_t bits_per_item)
Utility that converts a bandwidth in arbitrary units in both numerator and denominator to the same ba...
Definition: util.hpp:238
std::string buffers_dump_string(const Const_buffer_sequence &data, const std::string &indentation, size_t bytes_per_line)
Identical to buffers_to_ostream() but returns an std::string instead of writing to a given ostream.
Definition: util.hpp:505
Enum istream_to_enum(std::istream *is_ptr, Enum enum_default, Enum enum_sentinel, bool accept_num_encoding, bool case_sensitive, Enum enum_lowest)
Deserializes an enum class value from a standard input stream.
Definition: util.hpp:522
boost::span< T, E > Span
Short-hand for std::span-like type; that is contiguous sequence of objects with the first element of ...
Definition: util_fwd.hpp:353
void feed_args_to_ostream(std::ostream *os, T &&... ostream_args)
Function template that simply outputs arguments 2+ via << to the given ostream, in the order given.
Definition: util.hpp:361
std::ostream & operator<<(std::ostream &os, const Thread_local_state_registry< Thread_local_state_t > &val)
Serializes a Thread_local_state_registry to a standard output stream.
boost::asio::ip::address_v6 Ip_address_v6
Short-hand for the IPv6 address type.
Definition: util_fwd.hpp:224
boost::asio::ip::address_v4 Ip_address_v4
Short-hand for the IPv4 address type.
Definition: util_fwd.hpp:222
bool subtract_with_floor(Minuend *minuend, const Subtrahend &subtrahend, const Minuend &floor)
Performs *minuend -= subtrahend, subject to a floor of floor.
Definition: util.hpp:333
size_t deep_size(const std::string &val)
Estimate of memory footprint of the given value, including memory allocated on its behalf – but exclu...
Definition: util.cpp:186
constexpr Integer round_to_multiple(Integer dividend, Integer2 unit)
Returns the smallest integer >= the given integer dividend such that it is a multiple of the given in...
Definition: util.hpp:274
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:277
boost::shared_mutex Mutex_shared_non_recursive
Short-hand for non-reentrant, shared-or-exclusive mutex.
Definition: util_fwd.hpp:255
size_t size_unit_convert(From num_froms)
Answers the question what's the smallest integer number of Tos sufficient to verbatim store the given...
Definition: util.hpp:355
boost::shared_lock< Mutex_shared_non_recursive > Lock_guard_shared_non_recursive_sh
(Deprecated given C++1x) Short-hand for shared mode advanced-capability RAII lock guard for Mutex_sha...
Definition: util_fwd.hpp:312
bool in_open_open_range(T const &min_val, T const &val, T const &max_val)
Returns true if and only if the given value is within the given range, given as a (low,...
Definition: util.hpp:304
constexpr size_t DYNAMIC_EXTENT
Configures a Span at compile-time to have a variable, rather than constant, length (use it as templat...
Definition: util_fwd.hpp:46
bool in_open_closed_range(T const &min_val, T const &val, T const &max_val)
Returns true if and only if the given value is within the given range, given as a (low,...
Definition: util.hpp:288
boost::unique_lock< Mutex_non_recursive > Lock_guard_non_recursive
(Deprecated given C++1x) Short-hand for advanced-capability RAII lock guard for Mutex_non_recursive m...
Definition: util_fwd.hpp:295
void swap(Basic_blob< Allocator, SHARING > &blob1, Basic_blob< Allocator, SHARING > &blob2, log::Logger *logger_ptr) noexcept
Equivalent to blob1.swap(blob2).
boost::recursive_mutex Mutex_recursive
Short-hand for reentrant, exclusive mutex.
Definition: util_fwd.hpp:230
boost::unique_lock< Mutex_shared_non_recursive > Lock_guard_shared_non_recursive_ex
(Deprecated given C++1x) Short-hand for exclusive mode advanced-capability RAII lock guard for Mutex_...
Definition: util_fwd.hpp:321
boost::shared_lock< Mutex_noop_shared_non_recursive > Lock_guard_noop_shared_non_recursive_sh
(Deprecated given C++1x) Equivalent to Lock_guard_shared_non_recursive_sh but applied to Mutex_noop_s...
Definition: util_fwd.hpp:330
void ostream_op_to_string(std::string *target_str, T &&... ostream_args)
Writes to the specified string, as if the given arguments were each passed, via << in sequence,...
Definition: util.hpp:367
std::ostream & buffers_to_ostream(std::ostream &os, const Const_buffer_sequence &data, const std::string &indentation, size_t bytes_per_line)
Writes a multi- or single-line string representation of the provided binary data to an output stream,...
Definition: util.hpp:413
Task_engine::strand Strand
Short-hand for boost.asio strand, an ancillary class that works with Task_engine for advanced task sc...
Definition: util_fwd.hpp:150
bool in_closed_range(T const &min_val, T const &val, T const &max_val)
Returns true if and only if the given value is within the given range, inclusive.
Definition: util.hpp:280
boost::shared_ptr< void > Auto_cleanup
Helper type for setup_auto_cleanup().
Definition: util_fwd.hpp:217
boost::asio::io_context Task_engine
Short-hand for boost.asio event service, the central class of boost.asio.
Definition: util_fwd.hpp:147
boost::shared_lock< Shared_mutex > Shared_lock_guard
Short-hand for shared mode advanced-capability RAII lock guard, particuarly for Mutex_shared_non_recu...
Definition: util_fwd.hpp:287
std::string ostream_op_string(T &&... ostream_args)
Equivalent to ostream_op_to_string() but returns a new string by value instead of writing to the call...
Definition: util.hpp:381
boost::chrono::microseconds time_since_posix_epoch()
Get the current POSIX (Unix) time as a duration from the Epoch time point.
Definition: util.cpp:147
boost::unique_lock< Mutex_noop_shared_non_recursive > Lock_guard_noop_shared_non_recursive_ex
(Deprecated given C++1x) Equivalent to Lock_guard_shared_non_recursive_ex but applied to Mutex_noop_s...
Definition: util_fwd.hpp:339
boost::mutex Mutex_non_recursive
Short-hand for non-reentrant, exclusive mutex. ("Reentrant" = one can lock an already-locked-in-that-...
Definition: util_fwd.hpp:227
boost::asio::basic_waitable_timer< Fine_clock > Timer
boost.asio timer.
Definition: util_fwd.hpp:214
boost::null_mutex Mutex_noop_shared_non_recursive
Short-hand for a mutex type equivalent to util::Mutex_shared_non_recursive – except that the lock/unl...
Definition: util_fwd.hpp:263
boost::thread Thread
Short-hand for standard thread class.
Definition: util_fwd.hpp:90
boost::asio::ip::udp::endpoint Udp_endpoint
Short-hand for the UDP endpoint (IP/port) type.
Definition: util_fwd.hpp:220
constexpr Integer ceil_div(Integer dividend, Integer2 divisor)
Returns the result of the given non-negative integer divided by a positive integer,...
Definition: util.hpp:259