Flow 3.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/unordered_flat_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// Find doc headers near the bodies of these compound types.
49
50template<typename Key, typename Iterator, bool IS_ITER_TO_PAIR>
51class Linked_hash_key;
52template<typename Hash>
53class Linked_hash_key_hash;
54template<typename Pred>
55class Linked_hash_key_pred;
56class Thread_local_ptr_cache;
57
58/**
59 * The lookup structure used inside Linked_hash_map and Linked_hash_set. See the former's doc header(s).
60 *
61 * @note Make sure the value of #LINKED_HASH_KEY_SET_DEFAULT_N_BUCKETS is in sync with the target of
62 * this type alias. The constant's doc header explains.
63 *
64 * ### The actual target used ###
65 * It needs to be an `unordered_*set`, from somewhere, but for general use -- and this is general use, in that
66 * `Key` is specified by the `Linked_hash_map/set` user -- the Boost `unordered_flat_*` variants (with open
67 * addressing) are generally considered non-trivially faster than the vanilla alternative `unordered_*` ones.
68 * One loses pointer stability, but happily for us it does not matter:
69 * - Access to a pointer/iterator into this structure is never granted to the actual user. That's
70 * really the bottom line. For more context though:
71 * - What they do eventually/potentially access = copies of `Iterator`s; these are into the `list`, or whatever,
72 * inside `Linked_hash_map`, `Linked_hash_set`. (Internally `Iterator`s are probably pointers really.) That
73 * `list`-or-whatever has pointer stability, in fact, but the point is that *our* pointer-stability or lack
74 * thereof is not relevant.
75 *
76 * @tparam Key
77 * See Linked_hash_map, Linked_hash_set.
78 * @tparam Iterator
79 * Linked_hash_map::Iterator or Linked_hash_set::Iterator.
80 * @tparam Hash
81 * See Linked_hash_map, Linked_hash_set.
82 * @tparam Pred
83 * See Linked_hash_map, Linked_hash_set.
84 * @tparam IS_ITER_TO_PAIR
85 * `true` for Linked_hash_map, `false` for Linked_hash_set.
86 */
87template<typename Key, typename Iterator, typename Hash, typename Pred, bool IS_ITER_TO_PAIR>
88using Linked_hash_key_set = boost::unordered_flat_set<Linked_hash_key<Key, Iterator, IS_ITER_TO_PAIR>,
91
92// Constants.
93
94/**
95 * Value used by alias-target type of #Linked_hash_key_set as the default hash bucket count, if one does
96 * not explicitly specify it.
97 *
98 * ### The value ###
99 * Using `detail::` like this is technically uncool, but so far all alternatives look worse.
100 * We blame the somewhat annoying ctor API for unordered_*.
101 *
102 * @note There's a subtlety in that some of the `unordered_*` impls use `detail::default_bucket_count`; others
103 * use `detail::foa::default_bucket_count` (though, between you and me, both are equal to zero -- whatever
104 * it means -- in, say, Boost-1.92). So keep it in sync with the target of #Linked_hash_key_set.
105 */
106constexpr size_t LINKED_HASH_KEY_SET_DEFAULT_N_BUCKETS = boost::unordered::detail::foa::default_bucket_count;
107
108// Free functions.
109
110/**
111 * Helper that takes a non-negative duration of arbitrary precision/period and converts it to
112 * #Fine_duration, rounding up. Also, the input type's `max()` is translated to `Fine_duration::max()`.
113 *
114 * @tparam Rep
115 * See `boost::chrono::duration` documentation.
116 * @tparam Period
117 * See `boost::chrono::duration` documentation.
118 * @param dur
119 * A non-negative duration (or assertion trips).
120 * @return See above.
121 */
122template<typename Rep, typename Period>
123Fine_duration chrono_duration_to_fine_duration(const boost::chrono::duration<Rep, Period>& dur);
124
125/**
126 * Helper that takes a non-negative duration of arbitrary precision/period and converts it to
127 * #Fine_duration, rounding up; then adds it to `Fine_clock::now()` and returns the result.
128 * Also, the input type's `max()` is translated to `Fine_time_pt{}` (Epoch-valued -- i.e., zero-valued -- time point).
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_time_pt chrono_duration_from_now_to_fine_time_pt(const boost::chrono::duration<Rep, Period>& dur);
140
141/**
142 * Helper for FLOW_UTIL_WHERE_AM_I() that, given a pointer/length of a string in memory containing a path, returns
143 * a pointer/length into that same buffer that comprises the postfix
144 * just past the last directory separator or (if none exists) to all of it.
145 *
146 * ### Rationale for taking and returning #String_view this way ###
147 * There are 2 other alternatives. One is essentially to take `std::string` (or #String_view) and return new
148 * `std::string` (or some variation). That is un-great, because the main use case is to use this at log call sites,
149 * and creating temporary `std::string`s is best avoided; the ability to simply return a pointer into existing memory,
150 * -- particularly since it is likely to come from `__FILE__` (which is in static memory) -- might represent
151 * significant perf savings. So that leaves either the alternative we chose or a variation (which, historically, used
152 * to be the case) which is to take a `const char*` and return same, into that memory. The latter is an acceptable
153 * approach. #String_view, by comparison, does involve storing an extra bit of data, namely the length stored inside
154 * #String_view. We stipulate this is negligible in terms of RAM and copying costs when compared to doing same with
155 * the pointers alone... but what's the advantage? Answer: it may be small; but in order to search for the right-most
156 * dir separator character, one needs to internally find the NUL (a/k/a `strlen()`); with #String_view it is already
157 * available, so the linear search is unnecessary. Doesn't it cost cycles to set the length though? you ask.
158 * Answer: Not if one constructs the `#String_view`s involved cleverly. To wit:
159 *
160 * ### Instructions on how to best construct `String_view path` from `__FILE__` ###
161 * For max performance, do it in the same way as recommended when setting log::Msg_metadata::m_msg_src_file.
162 * Spoiler alert: Use `sizeof(__FILE__)` to obtain a compile-time length.
163 *
164 * ### `constexpr` ###
165 * Update: This function is now `constexpr`, so `path` must be known at compile-time; hence the above instructions
166 * (while still valid) apply in a different way. The raw performance doesn't necessarily matter (since it's "executed"
167 * by the compiler now). However, following those instructions (1) will help make `constexpr`ness easier to achieve
168 * (as the NUL-terminated #String_view ctor is less likely to be effectively `constexpr` depending on compiler; while
169 * the pointer+length ctor is more likely so); and (2) is good for perf in case `constexpr`ness is
170 * dropped in the future. It's less fragile is the point. Anyway, just do it!
171 *
172 * @param path
173 * String containing a path from a `__FILE__` macro. See instructions above for max perf.
174 * @return See above.
175 */
177
178/**
179 * Helper for FLOW_UTIL_WHERE_AM_I(), etc., that, given values for source code file name, function, and line number,
180 * returns an `std::string` equal to what FLOW_UTIL_WHERE_AM_I() would place into an `ostream`.
181 *
182 * For rationale of using #String_view instead of `const char*` for the string args see similar reasoning in
183 * get_last_path_segment() doc header. See also practical instructions on how to performantly obtain these args, in
184 * the doc header for `ARG_file` for FLOW_UTIL_WHERE_AM_I_FROM_ARGS().
185 *
186 * @param file
187 * See `ARG_file` in FLOW_UTIL_WHERE_AM_I_FROM_ARGS().
188 * @param function
189 * Full function name, as from `__FUNCTION__`. See instructions above for max perf.
190 * @param line
191 * Line number, as from `__LINE__`.
192 * @return String `X` (suitable for, for example: `std::cout << X << ": Hi!"`).
193 */
194std::string get_where_am_i_str(String_view file, String_view function, unsigned int line);
195
196} // 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...
Flow module containing miscellaneous general-use facilities that don't fit into any other Flow module...
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
boost::unordered_flat_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:90
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
constexpr size_t LINKED_HASH_KEY_SET_DEFAULT_N_BUCKETS
Value used by alias-target type of Linked_hash_key_set as the default hash bucket count,...
Definition: util_fwd.hpp:106
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
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