Flow-IPC 3.0.0
Flow-IPC project: Full implementation reference.
struc_fwd.hpp
Go to the documentation of this file.
1/* Flow-IPC: Structured Transport
2 * Copyright (c) 2023 Akamai Technologies, Inc.; and other contributors.
3 * Each commit is copyright by its respective author or author's employer.
4 *
5 * Licensed under the MIT License:
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE. */
24
25/// @file
26#pragma once
27
29#include "ipc/util/util_fwd.hpp"
30#include <flow/util/blob.hpp>
31#include <flow/util/stat/stat_fwd.hpp>
32#include <flow/util/stat/stat_set_list.hpp>
33#include <capnp/message.h>
34#include <boost/uuid/uuid.hpp>
35#include <vector>
36
37/**
38 * Sub-module of Flow-IPC module ipc::transport providing transmission of structured messages specifically.
39 * See ipc::transport doc header. As that notes, the big daddy here is struc::Channel.
40 *
41 * @see The guided Manual chapters @ref chan_struct and @ref chan_struct_advanced cover these topics.
42 *
43 * Be aware of sub-namespace ipc::transport::struc::shm which concerns itself with end-to-end-zero-copyable
44 * messages leveraging in-SHM storage. Normally there's no need for the user to know or worry about it,
45 * but for advanced applications, particularly extensions and customizations, one might delve into this area of
46 * the code. Otherwise it'll be used silently as important glue between various systems. Your journey would
47 * likely start with the struc::Builder concept doc header which would then lead you to
48 * struc::shm::Builder impl. That might lead you to specific SHM-providers like ipc::shm::classic.
49 */
51{
52
53// Types.
54
55// Find doc headers near the bodies of these compound types.
56
57template<typename Body_t, typename Builder_config_t>
58class Msg_out;
59template<typename Body_t, typename Reader_config_t>
60class Msg_in;
61class Capped_sz_capnp_message_builder;
62class Capped_sz_capnp_message_reader;
63class Channel_base;
64template<typename Owned_channel_t, typename Msg_body_t,
65 typename Builder_config_t, typename Reader_config_t>
66class Channel;
67class Heap_fixed_builder;
68class Heap_reader;
69struct Split_segment;
70struct Null_session;
71
72template<typename Capnp_reader>
73struct Ostreamable_capnp_brief;
74template<typename Capnp_reader>
75struct Ostreamable_capnp_full;
76
77/**
78 * A type used by struc::Channel for internal safety/security/auth needs. See in particular
79 * struc::Channel constructors, both the regular-channel one and the session-master-channel one.
80 * That said: The user of ipc::transport (aided by ipc::session) structured layer shall generally be unconcerned
81 * with this, in practice, as ipc::session machinery will take care of:
82 * - setting up the session master struc::Channel which will generate this token during initial setup (log-in);
83 * and
84 * - setting up further `struc::Channel`s as requested by the user (the preceding bullet's token shall be
85 * passed to each new struc::Channel and expected internally in all messages).
86 *
87 * However, if one plans to *create* a struc::Channel directly (as ipc::session does), then one must have some
88 * limited understanding of this guy's existence (if not the internal details).
89 *
90 * @internal
91 * As you can see: internally it is a UUID (RFC 4122 Universally Unique IDentifier) which is 128 bits (16 bytes)
92 * in size. It's also a POD (Plain Old Data object), meaning it's ctor-free (direct-initialized) and can be
93 * `memcpy()`d around and such. See boost.uuid docs (which are simple).
94 *
95 * ### Use and rationale thereof ###
96 * A session master channel struc::Channel, operating in server mode during the log-in phase, will (as of
97 * this writing anyway) generate this using the boost.uuid random UUID generator. From that point on all
98 * channels spawned through that guy (by ipc::session) will be cted with that token value; and all messages both
99 * in those channels and the original master channel (after the log-in message exchange) will send this value
100 * and ensure any in-message has that value (or immediately hose the channel -- auth failure). This is a
101 * safety (not really security, due to the lack of token invalidation at least) measure. It will reduce chances
102 * that "wires get crossed," and a message goes into the wrong channel somehow.
103 *
104 * That's how it's used. Is the random-generator method of UUID generation acceptable for this use?
105 *
106 * A bit of research (starting in the RFC perhaps; or Wikipedia) shows that collisions are so cosmically rare as to
107 * make it, quite officially, a non-concern. Even if one does not accept that, however, suppose a collision does
108 * occur: two channels happen to generate the same UUID on the same machine around the same time. This (essentially
109 * impossible) scenario would not cause either channel to break; it would only allow (in theory) a token check
110 * to succeed where it shouldn't, if the fabled wires-crossed scenario occurred. This is an acceptable level of risk.
111 *
112 * Conversely, perhaps using UUIDs for this is overkill. 128 bits isn't heavy, but perhaps something smaller --
113 * maybe even much smaller, like 32 bits or even 16 -- would improve perf without really reducing effectiveness
114 * given the above rationale. Indeed that's worth considering but only in the phase where perf optimization is
115 * the explicit goal. Until then (if that even happens) the ability to use the nice boost.uuid library instead
116 * of rolling our own jankier/smaller UUID-like thing (or whatever) is well worth the alleged perf cost.
117 *
118 * @todo Look into whether something smaller than RFC 4122 UUIDs can and should be used for #Session_token.
119 * This would be for perf but may well be unnecessary. See discussion near this to-do.
120 */
121using Session_token = boost::uuids::uuid;
122
123/**
124 * Sequence of 1+ segment descriptions, each representing a live writable segment (of a capnp serialization of a
125 * capnp-`struct`) and optional header/prefix area immediately preceding it. As of this writing this is specifically
126 * 1+ `Basic_blob` *pointers* to blobs that directly represent those segments+header(s) which must stay alive while
127 * these pointers may be dereferenced. In each `Basic_blob` [`begin()`, `end()`)
128 * is the serialization segment itself; and space before `begin()` (of size `start()`) may
129 * be reserved for framing prefix/header to preserve zero-copy when transmitting such serializations over
130 * an IPC "wire." (Area after `end()` up to `capacity()` could represent a framing postfix, though as of this writing
131 * we assume only a header might exist, for simplicity. As long as possible we shall avoid adding a postfix into the
132 * design.)
133 *
134 * ### Rationale ###
135 * Why represent the segment+header as `Basic_blob` specifically? Answer: The relevant serialization engine(s) could
136 * internally represent data structures (namely segments and frame-prefix and such) however they want, and indeed by
137 * choosing `Basic_blob*` here essentially we force that impl to be specifically that. That is a very reasonable
138 * structure (and less-feature-filled, slightly-higher-performing than the derivative `Blob`),
139 * but why force it? Indeed, as regards a public API, something merely describing locations and sizes *inside*
140 * the data structure of choice would be stylistically more direct and therefore more flexible/better. To wit
141 * #Segment_bufs (sequence of pointer + size pairs essentially) is almost such a thing; just it's not *quite* enough,
142 * because it does not directly/intuitively represent the header/prefix areas that might precede segments (but
143 * instead merely the segments themselves). So we choose `Basic_blob*` simply
144 * because it is (1) a decent choice for all impls in practice and (2) sufficiently-well describes both
145 * segments and frame headers nearby. It is slightly inflexible but acceptable overall.
146 *
147 * @todo As per nearby Rationale comment, `Segment_ptrs` element type would ideally be a view *into* `Blob`-or-similar
148 * instead of actual `Basic_blob*`, to decouple impl from API more cleanly. One approach might be to develop a
149 * `flow::util` class/template, a peer of the `flow::util::Blob` hierarchy, that specifically represents a view into a
150 * `Blob`-type-thing (perhaps 1 variant for mutable, 1 variant for immutable), perhaps analogously to how
151 * `span<uint8_t>` + `span<const uint8_t>` is each a view into `vector<uint8_t>` (minus the latter's capacity).
152 * It would therefore store a pointer, a size, a capacity, and a start-index -- representing a main buffer (`size()`
153 * in size), N-byte header/prefix (N = `start()`), and M-byte postfix (M = `capacity() - start() - size()`).
154 * (A more economical buffer+header version -- directly applicable here -- might store all of those minus the
155 * capacity, meaning there is no postfix area.) Possible names might be `Blob_view_const` (read-only view
156 * into buffer plus header plus postfix), `Blob_view_mutable` (same plus writable access),
157 * `Prefixed_byte_span_const` (`Blob_view_const` minus postfix area), `Prefixed_byte_span_mutable` (`Blob_view_mutable`
158 * minus postfix area). #Segment_ptrs would likely be `vector<Prefixed_byte_span_mutable>`.
159 */
160using Segment_ptrs = std::vector<flow::util::Blob_sans_log_context*>;
161
162/**
163 * Simpler cousin of #Segment_ptrs, this represents the IPC-transmissible representation of a capnp serialization
164 * of a capnp-`struct` including any framing header(s), expressed as simply a sequence of N read-only views, each
165 * containing a pointer to header-if-any-followed-by-serialization-segment and the size in bytes thereof.
166 *
167 * Note that while #Segment_ptrs contains info on header size, this `Segment_bufs` does not: So to properly interpret
168 * the given `Blob_const` element, one must know the size of the header therein (if any; by convention we can say that
169 * no header => header size is 0 => segment = entire `Blob_const`).
170 */
171using Segment_bufs = std::vector<util::Blob_const>;
172
173/**
174 * A simple data structure describing the segments (if any) in a #Segment_bufs (or similar) structure which had to
175 * be split (presumably due to size constraints); by following the indices/sizes into a post-split #Segment_bufs one
176 * can join the appropriate elements so as to obtain the original pre-split segments.
177 *
178 * The order of `Split_segment`s is strictly from left to right. A reasonable join algorithm, therefore, would
179 * iterate over a `Split_segments` in *reverse* order; for each Split_segment join the 2+ segments in the post-split
180 * #Segment_bufs (or similar) described therein, in-place. By doing this in reverse order, handling Split_segment
181 * A before B will not invalidate the start-index member in B.
182 *
183 * By convention #Split_segments shall include a Split_segment only if a segment actually needed to be split.
184 */
185using Split_segments = std::vector<Split_segment>;
186
187/**
188 * Short-hand for a high-performance blob structure that represents an IPC-incoming (sub-)segment 1+ of which
189 * make up the outer serialization of a given Msg_in. Its *exact* semantics are context-dependent, so it's best
190 * to read the API or context to determine such details.
191 */
192using Segment_blob_in = flow::util::Blob_sans_log_context;
193
194/**
195 * Message ID uniquely identifying outgoing message (Msg_out, among all other `Msg_out`s), per channel; and
196 * similarly incoming message (Msg_in, among `Msg_in`s), per channel. 0 is a sentinel value and not a valid
197 * user message ID. A message ID pertains to a *sent* or *received* *instance* of a user-created Msg_out
198 * (and its in-message counterpart Msg_in). A given Msg_out can be sent 2+ times through a given
199 * struc::Channel and even a *different* struc::Channel; a different message ID will pertain to each
200 * of those times for a given struc::Channel. Therefore there is no #msg_id_t *inside* a user Msg_out.
201 *
202 * This type is in the public API, as the message ID is made available in certain contexts for:
203 * - referring to an earlier-sent message, such as in struc::Channel::undo_expect_responses(); and
204 * - logging/reporting.
205 *
206 * @internal
207 * It can also be used as a sequence number and is therefore assigned from sequence 1, 2, ... (0 is sentinel).
208 *
209 * ### Rationale for type used ###
210 * Needs to be big enough to where there's no chance it overflows in a given channel for a given direction.
211 * Assume 1 billion messages per second, or about 2^30 msg/s. That would take 2^(64-30), or 2^34, seconds,
212 * or over 500 years, to overflow. So this should be fine. Moreover overflow is fine in that case, in practice,
213 * if this is used only as a unique ID; it would however in theory present problems if used as a sequence number.
214 */
215using msg_id_t = uint64_t;
216
217/// Alias for capnp's MessageBuilder interface. Rationale: as part of our API, we use our identifier style.
218using Capnp_msg_builder_interface = ::capnp::MessageBuilder;
219
220/// Alias for capnp's MessageReader interface. Rationale: as part of our API, we use our identifier style.
221using Capnp_msg_reader_interface = ::capnp::MessageReader;
222
223// Constants.
224
225/// A value for which `.is_nil()` is true.
227
228/// The only necessary value of empty-type Null_session.
229extern const Null_session NULL_SESSION;
230
231/**
232 * struc::Channel (and struc::sync_io::Channel) requires, for internal purposes, that any Msg_out transmitted over it
233 * was provided with a Struct_builder::Config that has `m_frame_prefix_sz` member set to this value (or larger if
234 * desired for some purpose). As of this writing that includes Heap_fixed_builder::Config::m_frame_prefix_sz
235 * (for heap-backed messages) and shm::Builder::Config::m_frame_prefix_sz (for SHM-backed ones).
236 *
237 * ### Rationale ###
238 * In typical usage patterns one need not assemble a Struct_builder::Config explicitly, but nothing forbids it,
239 * hence it seemed prudent to expose this publicly.
240 *
241 * Note that `Struct_builder`s and hence their `Config`s (formally speaking) may be used independently of
242 * struc::Channel, so it *is* conceivable to not need this value set (e.g., `0` would be quite conceivable).
243 * (In fact internally Flow-IPC might use these guys in various capacities and may well set `.m_frame_prefix_sz = 0`
244 * in some contexts.) That is to say, `m_frame_prefix_sz` should *not* simply be removed from our APIs and replaced by
245 * a constant all-over.
246 */
248
249// Free functions.
250
251/**
252 * Convenience function that returns an object passable to `ostream<<` to print a
253 * one-line/potentially-truncated representation to that stream, given an arbitrary capnp `Reader`.
254 *
255 * @param capnp_reader
256 * The `Reader` to presumably print. Tip: if you have a `Builder builder` to print then pass
257 * `builder.asReader()` here.
258 * @return See above.
259 */
260template<typename Capnp_reader>
261Ostreamable_capnp_brief<Capnp_reader> ostreamable_capnp_brief(const Capnp_reader& capnp_reader);
262
263/**
264 * Convenience function that returns an object passable to `ostream<<` to print a
265 * multi-line/pretty-printed/indented/full-length representation to that stream, given an arbitrary capnp `Reader`.
266 *
267 * @param capnp_reader
268 * The `Reader` to presumably print. Tip: if you have a `Builder builder` to print then pass
269 * `builder.asReader()` here.
270 * @return See above.
271 */
272template<typename Capnp_reader>
273Ostreamable_capnp_full<Capnp_reader> ostreamable_capnp_full(const Capnp_reader& capnp_reader);
274
275/**
276 * Prints string representation (one-line/potentially-truncated form) of the given capnp `Reader`, via proxy object,
277 * to the given `ostream`.
278 *
279 * @warning Potentially the entire underlying capnp tree shall be traversed to make the output work
280 * (even if ultimately the output is truncated for length). This can be quite slow. Do not use in
281 * perf-critical paths, unless verbose-logging (etc.) is enabled.
282 *
283 * @see ostreamable_capnp_brief(): Wrap your `Reader capnp_reader` (or `builder.asReader()`) in this call
284 * to make use of this output operator conveniently.
285 *
286 * @param os
287 * Stream to which to write.
288 * @param val
289 * Object to serialize.
290 * @return `os`.
291 */
292template<typename Capnp_reader>
293std::ostream& operator<<(std::ostream& os, const Ostreamable_capnp_brief<Capnp_reader>& val);
294
295/**
296 * Prints string representation (multi-line/pretty-printed/indented/full-length form) of the given capnp `Reader`,
297 * via proxy object, to the given `ostream`.
298 *
299 * @warning Potentially the entire underlying capnp tree shall be traversed to make the output work.
300 * This can be quite slow. Do not use in perf-critical paths, unless verbose-logging (etc.) is enabled.
301 *
302 * @see ostreamable_capnp_full(): Wrap your `Reader capnp_reader` (or `builder.asReader()`) in this call
303 * to make use of this output operator conveniently.
304 *
305 * @param os
306 * Stream to which to write.
307 * @param val
308 * Object to serialize.
309 * @return `os`.
310 */
311template<typename Capnp_reader>
312std::ostream& operator<<(std::ostream& os, const Ostreamable_capnp_full<Capnp_reader>& val);
313
314/**
315 * Prints string representation of the given struc::Channel to the given `ostream`.
316 *
317 * @relatesalso struc::Channel
318 *
319 * @param os
320 * Stream to which to write.
321 * @param val
322 * Object to serialize.
323 * @return `os`.
324 */
325template<typename Owned_channel_t, typename Msg_body_t,
326 typename Builder_config_t, typename Reader_config_t>
327std::ostream& operator<<(std::ostream& os,
328 const Channel<Owned_channel_t, Msg_body_t,
329 Builder_config_t, Reader_config_t>& val);
330
331/**
332 * Prints string representation of the given `Msg_out` to the given `ostream`.
333 * Namely it prints via Msg_out::to_ostream(); be sure to read perf notes on that!
334 *
335 * @relatesalso Msg_out
336 *
337 * @param os
338 * Stream to which to write.
339 * @param val
340 * Object to serialize.
341 * @return `os`.
342 */
343template<typename Body_t, typename Struct_builder_t>
344std::ostream& operator<<(std::ostream& os, const Msg_out<Body_t, Struct_builder_t>& val);
345
346/**
347 * Prints string representation of the given `Msg_in` to the given `ostream`.
348 *
349 * @relatesalso Msg_in
350 *
351 * @param os
352 * Stream to which to write.
353 * @param val
354 * Object to serialize.
355 * @return `os`.
356 */
357template<typename Body_t, typename Reader_config_t>
358std::ostream& operator<<(std::ostream& os, const Msg_in<Body_t, Reader_config_t>& val);
359
360/**
361 * Prints string representation of the given `Heap_fixed_builder` to the given `ostream`.
362 *
363 * @relatesalso Heap_fixed_builder
364 *
365 * @param os
366 * Stream to which to write.
367 * @param val
368 * Object to serialize.
369 * @return `os`.
370 */
371std::ostream& operator<<(std::ostream& os, const Heap_fixed_builder& val);
372
373/**
374 * Prints string representation of the given `Heap_reader` to the given `ostream`.
375 *
376 * @relatesalso Heap_reader
377 *
378 * @param os
379 * Stream to which to write.
380 * @param val
381 * Object to serialize.
382 * @return `os`.
383 */
384std::ostream& operator<<(std::ostream& os, const Heap_reader& val);
385
386} // namespace ipc::transport::struc
387
388/// Stats-related sub-namespace, for ADL segregation and general organization.
390{
391
392// Types.
393
394// Find doc headers near the bodies of these compound types.
395
396struct Channel_sync_req_stats;
397struct Channel_stats;
398struct Histo_cfg;
399struct Pure_heap_tag;
400struct Serializer_stats;
401template<typename Cfg>
402struct Serializer_stats_p;
403struct Heap_serializer_stats_cfg;
404
405/// Default-constructible Serializer_stats variant for pure-heap user messages. See Serializer_stats doc header.
407
408/**
409 * Pure-heap (non-SHM) cumulative-#Heap_serializer_stats singleton: convenience alias for the default
410 * `flow::util::stat::Global_stats` instantiated with Pure_heap_tag.
411 *
412 * @todo Consider changing definition of alias struc::stat::Heap_serializer_global_stats from using
413 * `N == 1` to something larger, so that the user can optionally -- while still using this global stats-holder --
414 * further categorize stats according to their custom needs. Also consider similar steps in
415 * such alias(es) in struc::shm::stat. (Note various relevant APIs allow one to simply pass-in a
416 * `Serializer_stats*` (et al) directly -- and the user can maintain their own `Global_stats` or
417 * `static Stat_set_list` and lightning-quickly obtain the aforementioned `*` therefrom. So flexibility already
418 * exists on that front; but here we use a `Global_stats` for a reason already; can make use of it more fully
419 * this way.)
420 * One tactical idea is that factories like struc::Channel::heap_fixed_builder_config() can take an optional
421 * arg, defaulting to 0, which would cause such a factory to select the `Global_stats` slot. Slot 0 would
422 * continue to, by convention be the default/catch-all one; and the user can designate other slots for their own
423 * purposes.
424 */
425using Heap_serializer_global_stats = flow::util::stat::Global_stats<Pure_heap_tag, Heap_serializer_stats, 1>;
426
427// Free functions.
428
429/**
430 * Grabs a snapshot of the process-global pure-heap serializer stats -- the #Heap_serializer_global_stats
431 * singleton -- into `*target_stats` which can then be read/printed/aggregated at leisure.
432 *
433 * This covers all of serializer global-land for a *pure-heap* (non-SHM) application. A SHM-backed application
434 * has 2 more such global stat-sets; grab all 3 in one call via struc::shm::stat::serializer_info_dump() instead.
435 *
436 * (This does not affect any serializer object that has been redirected -- via the relevant builder/reader config
437 * knobs -- to accumulate into a custom Serializer_stats instead of the default global.)
438 *
439 * @param target_stats
440 * The stats are assigned here (via `flow::util::stat::stats_assign()`). Must not be null.
441 */
443
444/**
445 * Prints string representation -- `flow::util::stat::print()` output -- of the given Serializer_stats
446 * (or variant thereof, e.g. #Heap_serializer_stats) to the given `ostream`.
447 *
448 * @note To be honest `os << print(val)` is equally available, as for any `Stat_set`; we add this direct
449 * `operator<<` merely so that the heap_serializer_info_dump() experience is symmetrical with "true"
450 * info-dumping a-la struc::shm::stat::Serializer_info_dump (grab everything with one free function;
451 * print with `<<`) -- there is just one `struct` here, so it is simpler.
452 *
453 * @relatesalso Serializer_stats
454 *
455 * @param os
456 * Stream to which to write.
457 * @param val
458 * Object to serialize.
459 * @return `os`.
460 */
461std::ostream& operator<<(std::ostream& os, const Serializer_stats& val);
462
463/**
464 * Declares the stats for Channel_stats. Not invoked directly except by `flow::util::stat` internals,
465 * or when composing this stat-set into another.
466 * @see `flow::util::stat` namespace doc header for background on the declare/visit mechanism.
467 *
468 * @tparam Visitor
469 * See above.
470 * @param name_prefix
471 * See above.
472 * @param src_stats
473 * See above.
474 * @param target_stats
475 * See above.
476 * @param visitor
477 * See above.
478 */
479template<typename Visitor>
480void declare_stats(const flow::util::stat::Stat_name& name_prefix,
481 const Channel_stats* src_stats, Channel_stats* target_stats,
482 Visitor&& visitor);
483
484/**
485 * Declares the stats for Channel_sync_req_stats. Not invoked directly except by `flow::util::stat` internals,
486 * or when composing this stat-set into another.
487 * @see `flow::util::stat` namespace doc header for background on the declare/visit mechanism.
488 *
489 * @tparam Visitor
490 * See above.
491 * @param name_prefix
492 * See above.
493 * @param src_stats
494 * See above.
495 * @param target_stats
496 * See above.
497 * @param visitor
498 * See above.
499 */
500template<typename Visitor>
501void declare_stats(const flow::util::stat::Stat_name& name_prefix,
502 const Channel_sync_req_stats* src_stats, Channel_sync_req_stats* target_stats,
503 Visitor&& visitor);
504
505/**
506 * Declares the stats for Serializer_stats. Not invoked directly except by `flow::util::stat` internals,
507 * or when composing this stat-set into another.
508 * @see `flow::util::stat` namespace doc header for background on the declare/visit mechanism.
509 *
510 * @tparam Visitor
511 * See above.
512 * @param name_prefix
513 * See above.
514 * @param src_stats
515 * See above.
516 * @param target_stats
517 * See above.
518 * @param visitor
519 * See above.
520 */
521template<typename Visitor>
522void declare_stats(const flow::util::stat::Stat_name& name_prefix,
523 const Serializer_stats* src_stats, Serializer_stats* target_stats,
524 Visitor&& visitor);
525
526} // namespace ipc::transport::struc::stat
527
528/**
529 * `sync_io`-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::struc.
530 * Namely transport::struc::sync_io::Channel <=> transport::struc::Channel.
531 *
532 * @see util::sync_io doc header -- describes the general `sync_io` pattern we are following.
533 */
535{
536
537// Types.
538
539// Find doc headers near the bodies of these compound types.
540
541template<typename Owned_channel_t, typename Msg_body_t,
542 typename Builder_config_t, typename Reader_config_t>
543class Channel;
544
545// Free functions.
546
547/**
548 * Prints string representation of the given struc::sync_io::Channel to the given `ostream`.
549 *
550 * @relatesalso struc::sync_io::Channel
551 *
552 * @param os
553 * Stream to which to write.
554 * @param val
555 * Object to serialize.
556 * @return `os`.
557 */
558template<typename Owned_channel_t, typename Msg_body_t,
559 typename Builder_config_t, typename Reader_config_t>
560std::ostream& operator<<(std::ostream& os,
561 const Channel<Owned_channel_t, Msg_body_t,
562 Builder_config_t, Reader_config_t>& val);
563
564} // namespace ipc::transport::struc::sync_io
565
566/// Stats-related sub-namespace, for ADL segregation and general organization.
568{
569
570// Types.
571
572// Find doc headers near the bodies of these compound types.
573
574struct Channel_stats;
575
576// Free functions.
577
578/**
579 * Declares the stats for Channel_stats. Not invoked directly except by `flow::util::stat` internals,
580 * or when composing this stat-set into another.
581 * @see `flow::util::stat` namespace doc header for background on the declare/visit mechanism.
582 *
583 * @tparam Visitor
584 * See above.
585 * @param name_prefix
586 * See above.
587 * @param src_stats
588 * See above.
589 * @param target_stats
590 * See above.
591 * @param visitor
592 * See above.
593 */
594template<typename Visitor>
595void declare_stats(const flow::util::stat::Stat_name& name_prefix,
596 const Channel_stats* src_stats, Channel_stats* target_stats,
597 Visitor&& visitor);
598
599} // namespace ipc::transport::struc::sync_io::stat
600
601/**
602 * Small group of miscellaneous utilities to ease work with capnp (Cap'n Proto), joining its `capnp` namespace.
603 * As of this writing circumstances have to be very particular and rare indeed for something to actually be added
604 * by us to this namespace. As I write this, it contains only `operator<<(std::ostream&, capnp::Text::Reader&)`.
605 */
606namespace capnp
607{
608
609/**
610 * Prints string representation of the given `capnp::Text::Reader` to the given `ostream`.
611 *
612 * ### Rationale for existence ###
613 * Well, capnp does not provide it, even though it provides a conversion operator to `string` and such; and
614 * it's nice to be able to print these (particularly when logging with `FLOW_LOG_*()`).
615 * For whatever reason the auto-conversion operator does not "kick in" when placed in a
616 * an `ostream<<` context; so such printing does not compile (nor does `lexical_cast<string>`).
617 *
618 * It won't be forced on anyone that doesn't include the present header.
619 *
620 * @param os
621 * Stream to which to write.
622 * @param val
623 * Object to serialize.
624 * @return `os`.
625 */
626std::ostream& operator<<(std::ostream& os, const Text::Reader& val);
627
628} // namespace capnp
Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...
Definition: channel.hpp:645
typename Sync_io_obj::Msg_out Msg_out
Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...
Definition: channel.hpp:692
std::ostream & operator<<(std::ostream &os, const Channel< Owned_channel_t, Msg_body_t, Builder_config_t, Reader_config_t > &val)
Prints string representation of the given struc::Channel to the given ostream.
typename Sync_io_obj::Msg_in Msg_in
Encapsulation of any in-message instance received by a *this of this type.
Definition: channel.hpp:701
~Simplest possible impl of Struct_builder concept that represents the capnp payload directly in heap ...
Implements Struct_reader concept by straightforwardly interpreting a serialization by Heap_fixed_buil...
sync_io-pattern counterpart to async-I/O-pattern transport::struc::Channel.
Definition: channel.hpp:386
Small group of miscellaneous utilities to ease work with capnp (Cap'n Proto), joining its capnp names...
std::ostream & operator<<(std::ostream &os, const Text::Reader &val)
Prints string representation of the given capnp::Text::Reader to the given ostream.
struc::Channel< Channel_obj, Message_body, Builder::Config, Reader::Config > Channel
Convenience alias: Use this when constructing a struc::Channel with tag Channel_base::S_SERIALIZE_VIA...
Definition: classic.hpp:42
Reader< ipc::shm::classic::Pool_arena > Reader
Convenience alias: transport::struc::shm::Reader that works with boost.ipc.shm pools from ipc::shm::c...
Definition: classic_fwd.hpp:39
Stats-related sub-namespace, for ADL segregation and general organization.
flow::util::stat::Global_stats< Pure_heap_tag, Heap_serializer_stats, 1 > Heap_serializer_global_stats
Pure-heap (non-SHM) cumulative-Heap_serializer_stats singleton: convenience alias for the default flo...
Definition: struc_fwd.hpp:425
std::ostream & operator<<(std::ostream &os, const Serializer_stats &val)
Prints string representation – flow::util::stat::print() output – of the given Serializer_stats (or v...
Serializer_stats_p< Heap_serializer_stats_cfg > Heap_serializer_stats
Default-constructible Serializer_stats variant for pure-heap user messages. See Serializer_stats doc ...
Definition: struc_fwd.hpp:406
void declare_stats(const flow::util::stat::Stat_name &name_prefix, const Channel_sync_req_stats *src_stats, Channel_sync_req_stats *target_stats, Visitor &&visitor)
Declares the stats for Channel_sync_req_stats.
void heap_serializer_info_dump(Heap_serializer_stats *target_stats)
Grabs a snapshot of the process-global pure-heap serializer stats – the Heap_serializer_global_stats ...
Stats-related sub-namespace, for ADL segregation and general organization.
Definition: struc_fwd.hpp:568
void declare_stats(const flow::util::stat::Stat_name &name_prefix, const Channel_stats *src_stats, Channel_stats *target_stats, Visitor &&visitor)
Declares the stats for Channel_stats.
sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport::st...
Definition: struc_fwd.hpp:535
std::ostream & operator<<(std::ostream &os, const Channel< Owned_channel_t, Msg_body_t, Builder_config_t, Reader_config_t > &val)
Prints string representation of the given struc::sync_io::Channel to the given ostream.
Sub-module of Flow-IPC module ipc::transport providing transmission of structured messages specifical...
Definition: channel.cpp:31
Ostreamable_capnp_brief< Capnp_reader > ostreamable_capnp_brief(const Capnp_reader &capnp_reader)
Convenience function that returns an object passable to ostream<< to print a one-line/potentially-tru...
Definition: util.hpp:71
static constexpr size_t BUILDER_CONFIG_FRAME_PREFIX_SZ_VIA_STRUC_CHANNEL
struc::Channel (and struc::sync_io::Channel) requires, for internal purposes, that any Msg_out transm...
Definition: struc_fwd.hpp:247
Ostreamable_capnp_full< Capnp_reader > ostreamable_capnp_full(const Capnp_reader &capnp_reader)
Convenience function that returns an object passable to ostream<< to print a multi-line/pretty-printe...
Definition: util.hpp:77
std::vector< Split_segment > Split_segments
A simple data structure describing the segments (if any) in a Segment_bufs (or similar) structure whi...
Definition: struc_fwd.hpp:185
boost::uuids::uuid Session_token
A type used by struc::Channel for internal safety/security/auth needs.
Definition: struc_fwd.hpp:121
::capnp::MessageReader Capnp_msg_reader_interface
Alias for capnp's MessageReader interface. Rationale: as part of our API, we use our identifier style...
Definition: struc_fwd.hpp:221
std::vector< flow::util::Blob_sans_log_context * > Segment_ptrs
Sequence of 1+ segment descriptions, each representing a live writable segment (of a capnp serializat...
Definition: struc_fwd.hpp:160
const Null_session NULL_SESSION
The only necessary value of empty-type Null_session.
const Session_token NULL_SESSION_TOKEN
A value for which .is_nil() is true.
Definition: channel.cpp:35
std::ostream & operator<<(std::ostream &os, const Heap_fixed_builder &val)
Prints string representation of the given Heap_fixed_builder to the given ostream.
flow::util::Blob_sans_log_context Segment_blob_in
Short-hand for a high-performance blob structure that represents an IPC-incoming (sub-)segment 1+ of ...
Definition: struc_fwd.hpp:192
std::vector< util::Blob_const > Segment_bufs
Simpler cousin of Segment_ptrs, this represents the IPC-transmissible representation of a capnp seria...
Definition: struc_fwd.hpp:171
uint64_t msg_id_t
Message ID uniquely identifying outgoing message (Msg_out, among all other Msg_outs),...
Definition: struc_fwd.hpp:215
Value for Struct_builder::Session when no extra information is needed when serializing Struct_builder...
Proxy object referring to a capnp Reader for straightforward output via overloaded ostream<<: one-lin...
Definition: util.hpp:46
Proxy object referring to a capnp Reader for straightforward output via overloaded ostream<<: multi-l...
Definition: util.hpp:60
Cumulative stats from a struc::Channel, composing the underlying sync_io::stat::Channel_stats with st...
Stats specific to Channel::sync_request() – the blocking synchronous request-response API available o...
Templated no-data, non-polymorphic subclass of Serializer_stats whose precipitating use-case is to sa...
Cumulative stats describing capnp-driven memory-allocation activities on behalf of a struc::Struct_bu...
Cumulative stats from a struc::sync_io::Channel, covering both send and receive directions as well as...