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 "flow/common.hpp"
23#include <boost/shared_ptr.hpp>
24#include <boost/unordered_set.hpp>
25
26/// @cond
27// -^- Doxygen, please ignore the following.
28
29/* This strangeness is a work-around a Boost bug which manifests itself at least in g++ and clang++ in
30 * C++11 mode, when trying to use ratio<>::num and ::den. Without this, those two symbols, per each ratio<>
31 * type directly used, each get an undefined reference linker error. See https://svn.boost.org/trac10/ticket/13191,
32 * not fixed as of this writing. @todo: Revisit. */
33#ifndef BOOST_NO_CXX11_CONSTEXPR
34template <boost::intmax_t N, boost::intmax_t D>
35const boost::intmax_t boost::ratio<N, D>::num;
36template <boost::intmax_t N, boost::intmax_t D>
37const boost::intmax_t boost::ratio<N, D>::den;
38#endif
39
40// -v- Doxygen, please stop ignoring.
41/// @endcond
42
43namespace flow::util
44{
45
46// Types.
47
48/* (The @namespace line shouldn't be needed, but there must be some Doxygen bug causing that doc header to get
49 * merged into the succeeding function's. Who knows? @todo Look into it more in copious spare time.
50 *
51 * Update: That was with Doxygen 1.8.11 through 1.8.15. In 1.8.16, it's still true; plus another bug appeared:
52 * The first sentence (up to the first period) is supposed to interpreted, with certain Doxygen config,
53 * as @brief, meaning the brief summary of the namespace; this feature is used constantly, not just in this
54 * spot. Well, for some reason that Doxygen version took the @brief to be blank (shows up as blank in the
55 * namespaces list page and the namespace page itself), whereas before it was fine. Since it's not happening
56 * for anything else I made it an explicit @brief here and called it a day; I guess the Doxygen parser is
57 * getting doubly confused; not sure. @todo Sigh, untangle this at some point; maybe Doxygen gets fixed;
58 * file bug against Doxygen. This is the only (documented) namespace alias in the code, as of this writing, so
59 * maybe that is why it is "special.") */
60
61/**
62 * @namespace flow::util::bind_ns
63 *
64 * @brief Hack namespace alias to enable use of `bind` and related utilities like `cref` in the face of strange observed
65 * compiler behavior.
66 *
67 * The code in the past used `bind` and its helpers `cref` and `ref` fairly extensively. (Vast majority of `bind`s are
68 * now replaced with superior uses of lambdas, with the upgrade to C++1x. So it's far less extensive than in past.)
69 * However, there is something odd going on with namespace resolution for
70 * these guys. At least in the clang version used as of this writing, `bind` somehow
71 * works without qualification, as does `cref` (and thus probably `ref`); I really don't know why. I'd like to use
72 * the `boost::` versions, though, specifically (for stylistic reasons explained elsewhere). More importantly, I don't
73 * want to use something that mysteriously works without qualification -- is `std::` somehow being forced with some
74 * phantom `using namespace` from some evil header somewhere? I am not sure as of this writing. In any case,
75 * this allows one to just say `using util::bind_ns::bind` and then use `bind()` without qualification in that
76 * block (typically function/method) without worrying that some weird unqualified guy will be used.
77 *
78 * Caveat 1: I don't know why, but in the aforementioned clang, `using util::bind_ns::cref` makes `cref()` become
79 * ambiguous with some `std::cref`; it's quite unclear why the same complaint then doesn't happen for `bind()` itself.
80 * In that case, when an error is encountered, get rid of the `using` and instead qualify it as `util::bind_ns::cref()`.
81 * It sucks, but at least it's clear.
82 *
83 * Caveat 2: I haven't built in MS Visual Studio in quite a while (though it did use to work at one point), but back
84 * then I remember some VC++-specific trouble with `bind()` resolution. Possibly it's related to the above.
85 * Anyway, use `bind_ns` as needed to get around any such compile errors.
86 *
87 * Note: Knowing of this phantom `bind()` that's magically available sans qualification, I also tried to use
88 * unqualified `cout` and `endl` in the same context but thankfully got the expected errors in clang saying
89 * these identifiers do not exist but suggesting the use of `std::cout` and `std::endl`. So, at least it's not
90 * all of `std` being forced on the code.
91 *
92 * @todo Investigate deeply the cause of the strange behavior with unqualified `bind()` and others described
93 * above this line in the source code.
94 */
95namespace bind_ns = boost;
96
97// Find doc headers near the bodies of these compound types.
98
99template<typename Key, typename Iterator, bool IS_ITER_TO_PAIR>
100class Linked_hash_key;
101template<typename Hash>
103template<typename Pred>
105
106/**
107 * The lookup structure used inside Linked_hash_map and Linked_hash_set. See the former's doc header(s).
108 *
109 * @tparam Key
110 * See Linked_hash_map, Linked_hash_set.
111 * @tparam Iterator
112 * Linked_hash_map::Iterator or Linked_hash_set::Iterator.
113 * @tparam Hash
114 * See Linked_hash_map, Linked_hash_set.
115 * @tparam Pred
116 * See Linked_hash_map, Linked_hash_set.
117 * @tparam IS_ITER_TO_PAIR
118 * `true` for Linked_hash_map, `false` for Linked_hash_set.
119 */
120template<typename Key, typename Iterator, typename Hash, typename Pred, bool IS_ITER_TO_PAIR>
121using Linked_hash_key_set = boost::unordered_set<Linked_hash_key<Key, Iterator, IS_ITER_TO_PAIR>,
124// Free functions.
125
126/**
127 * Helper that takes a non-negative duration of arbitrary precision/period and converts it to
128 * #Fine_duration, rounding up. Also, the input type's `max()` is translated to `Fine_duration::max()`.
129 *
130 * @tparam Rep
131 * See `boost::chrono::duration` documentation.
132 * @tparam Period
133 * See `boost::chrono::duration` documentation.
134 * @param dur
135 * A non-negative duration (or assertion trips).
136 * @return See above.
137 */
138template<typename Rep, typename Period>
139Fine_duration chrono_duration_to_fine_duration(const boost::chrono::duration<Rep, Period>& dur);
140
141/**
142 * Helper that takes a non-negative duration of arbitrary precision/period and converts it to
143 * #Fine_duration, rounding up; then adds it to `Fine_clock::now()` and returns the result.
144 * Also, the input type's `max()` is translated to `Fine_time_pt{}` (Epoch-valued -- i.e., zero-valued -- time point).
145 *
146 * @tparam Rep
147 * See `boost::chrono::duration` documentation.
148 * @tparam Period
149 * See `boost::chrono::duration` documentation.
150 * @param dur
151 * A non-negative duration (or assertion trips).
152 * @return See above.
153 */
154template<typename Rep, typename Period>
155Fine_time_pt chrono_duration_from_now_to_fine_time_pt(const boost::chrono::duration<Rep, Period>& dur);
156
157/**
158 * Helper for FLOW_UTIL_WHERE_AM_I() that, given a pointer/length of a string in memory containing a path, returns
159 * a pointer/length into that same buffer that comprises the postfix
160 * just past the last directory separator or (if none exists) to all of it.
161 *
162 * ### Rationale for taking and returning #String_view this way ###
163 * There are 2 other alternatives. One is essentially to take `std::string` (or #String_view) and return new
164 * `std::string` (or some variation). That is un-great, because the main use case is to use this at log call sites,
165 * and creating temporary `std::string`s is best avoided; the ability to simply return a pointer into existing memory,
166 * -- particularly since it is likely to come from `__FILE__` (which is in static memory) -- might represent
167 * significant perf savings. So that leaves either the alternative we chose or a variation (which, historically, used
168 * to be the case) which is to take a `const char*` and return same, into that memory. The latter is an acceptable
169 * approach. #String_view, by comparison, does involve storing an extra bit of data, namely the length stored inside
170 * #String_view. We stipulate this is negligible in terms of RAM and copying costs when compared to doing same with
171 * the pointers alone... but what's the advantage? Answer: it may be small; but in order to search for the right-most
172 * dir separator character, one needs to internally find the NUL (a/k/a `strlen()`); with #String_view it is already
173 * available, so the linear search is unnecessary. Doesn't it cost cycles to set the length though? you ask.
174 * Answer: Not if one constructs the `#String_view`s involved cleverly. To wit:
175 *
176 * ### Instructions on how to best construct `String_view path` from `__FILE__` ###
177 * For max performance, do it in the same way as recommended when setting log::Msg_metadata::m_msg_src_file.
178 * Spoiler alert: Use `sizeof(__FILE__)` to obtain a compile-time length.
179 *
180 * ### `constexpr` ###
181 * Update: This function is now `constexpr`, so `path` must be known at compile-time; hence the above instructions
182 * (while still valid) apply in a different way. The raw performance doesn't necessarily matter (since it's "executed"
183 * by the compiler now). However, following those instructions (1) will help make `constexpr`ness easier to achieve
184 * (as the NUL-terminated #String_view ctor is less likely to be effectively `constexpr` depending on compiler; while
185 * the pointer+length ctor is more likely so); and (2) is good for perf in case `constexpr`ness is
186 * dropped in the future. It's less fragile is the point. Anyway, just do it!
187 *
188 * @param path
189 * String containing a path from a `__FILE__` macro. See instructions above for max perf.
190 * @return See above.
191 */
193
194/**
195 * Helper for FLOW_UTIL_WHERE_AM_I(), etc., that, given values for source code file name, function, and line number,
196 * returns an `std::string` equal to what FLOW_UTIL_WHERE_AM_I() would place into an `ostream`.
197 *
198 * For rationale of using #String_view instead of `const char*` for the string args see similar reasoning in
199 * get_last_path_segment() doc header. See also practical instructions on how to performantly obtain these args, in
200 * the doc header for `ARG_file` for FLOW_UTIL_WHERE_AM_I_FROM_ARGS().
201 *
202 * @param file
203 * See `ARG_file` in FLOW_UTIL_WHERE_AM_I_FROM_ARGS().
204 * @param function
205 * Full function name, as from `__FUNCTION__`. See instructions above for max perf.
206 * @param line
207 * Line number, as from `__LINE__`.
208 * @return String `X` (suitable for, for example: `std::cout << X << ": Hi!"`).
209 */
210std::string get_where_am_i_str(String_view file, String_view function, unsigned int line);
211
212} // namespace flow::util
The internal-use Hash functor wrapper, used as the hasher type in internal-use set-type Linked_hash_k...
The internal-use Pred functor wrapper, used as the key-equality-determiner type in internal-use set-t...
The internal-use key/iterator-wrapper, used as the key type in internal-use set-type Linked_hash_key_...
Definition: linked_hash.hpp:53
Flow module containing miscellaneous general-use facilities that don't fit into any other Flow module...
Definition: basic_blob.hpp:31
constexpr String_view get_last_path_segment(String_view full_path)
Helper for FLOW_UTIL_WHERE_AM_I() that, given a pointer/length of a string in memory containing a pat...
Definition: util.hpp:54
std::string get_where_am_i_str(String_view file, String_view function, unsigned int line)
Helper for FLOW_UTIL_WHERE_AM_I(), etc., that, given values for source code file name,...
Definition: util.cpp:27
Fine_time_pt chrono_duration_from_now_to_fine_time_pt(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:42
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::unordered_set< Linked_hash_key< Key, Iterator, IS_ITER_TO_PAIR >, Linked_hash_key_hash< Hash >, Linked_hash_key_pred< Pred > > Linked_hash_key_set
The lookup structure used inside Linked_hash_map and Linked_hash_set.
Definition: util_fwd.hpp:123
Basic_string_view< char > String_view
Commonly used char-based Basic_string_view. See its doc header.
Fine_clock::duration Fine_duration
A high-res time duration as computed from two Fine_time_pts.
Definition: common.hpp:405
Fine_clock::time_point Fine_time_pt
A high-res time point as returned by Fine_clock::now() and suitable for precise time math in general.
Definition: common.hpp:402