Flow-IPC 3.0.0
Flow-IPC project: Full implementation reference.
shm_fwd.hpp
Go to the documentation of this file.
1/* Flow-IPC: Shared Memory
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
21/**
22 * ipc::session sub-namespace that groups together facilities for SHM-backed sessions, particularly augmenting
23 * #Client_session, #Server_session, and Session_server classes by providing SHM-backed zero-copy functionality.
24 * ipc::session::shm is itself empty or almost empty; but for each possible SHM-provider there is a further
25 * sub-namespace; for example ipc::session::shm::classic.
26 *
27 * @see The guided Manual chapters @ref chan_struct_advanced and @ref transport_shm cover SHM-backed sessions in use.
28 *
29 * ### Background ###
30 * ipc::shm provides SHM facilities, including ipc::shm::classic and ipc::shm::arena_lend::jemalloc, that can be used
31 * stand-alone, without ipc::session. As with ipc::transport, though, this is not very convenient.
32 * ipc::session is well integrated with ipc::shm in that it provides certain pre-made arenas and simplifies
33 * transmission of handles to SHM-constructed objects and allows to place transport::struc::Channel
34 * out-messages into SHM instead of heap -- achieving full zero-copy if desired. ipc::session::shm is where
35 * this support lives.
36 *
37 * ### Details ###
38 * If you want these features, everything in the "Overview of relevant APIs" section (of ipc::session doc header)
39 * still applies identically, except you shall choose different types rather than #Client_session, #Server_session,
40 * Session_server. Firstly decide which SHM-provider; as of this writing ipc::shm::classic::Pool_arena or
41 * ipc::shm::arena_lend::jemalloc. For illustration let's assume you chose the former. Then:
42 * - Use shm::classic::Client_session in place of vanilla #Client_session.
43 * - Use shm::classic::Session_server in place of vanilla Session_server.
44 * - This will emit shm::classic::Server_session in place of vanilla #Server_session.
45 *
46 * We strongly recommend making yourself aliases as shown below, then from that point on obtaining all subsequent
47 * ipc::session types via aliases contained within those aliases (and then more aliases off those
48 * aliases as needed). The idea is to have only one point in the code where the SHM-backing (or no SHM backing)
49 * of the system are specified (simply by indicating the namespace of the top-level `Session_server` or `Client_session`
50 * type of choice), so that it can be easily changed to another, a-la generic programming.
51 *
52 * Server-side:
53 *
54 * ~~~
55 * using Session_server = ipc::session::shm::classic::Session_server
56 * <...>; // Compile-time session-configuring knobs go here.
57 * // ^-- Substitute shm::arena_lend::jemalloc::Session_server or even non-zero-copy plain Session_server as desired.
58 *
59 * // From this point on, no need to mention `ipc::session` again. In particular, e.g.:
60 *
61 * using Session = typename Session_server::Server_session_obj;
62 * template<typename Message_body>
63 * using Structured_channel = typename Session::template Structured_channel<Message_body>;
64 *
65 * // Off we go! Use the types as needed.
66 *
67 * // ...
68 * Session session; // Maybe fill it out with Session_server::async_accept() following this.
69 * // ...
70 * Structured_channel<MessageSchemaRootOfTheGods> cool_channel(...);
71 * // ...
72 * ~~~
73 *
74 * Client-side:
75 *
76 * ~~~
77 * using Session = ipc::session::shm::classic::Client_session
78 * <...>; // Matching (to server-side) knobs go here.
79 * // ^-- Substitute shm::arena_lend::jemalloc::Client_session or even non-zero-copy plain Client_session as desired.
80 *
81 * // From this point on, no need to mention `ipc::session` again. In particular, e.g.:
82 *
83 * using Session = typename Session_server::Server_session_obj;
84 * template<typename Message_body>
85 * using Structured_channel = typename Session::template Structured_channel<Message_body>;
86 *
87 * // Off we go! Use the types as needed.
88 *
89 * // ...
90 * Session session{...}; // Maybe .sync_connect() following this.
91 * // ...
92 * Structured_channel<MessageSchemaRootOfTheGods> cool_channel{...};
93 * // ...
94 * ~~~
95 *
96 * Entering PEER state is exactly identical to the vanilla APIs (the differences are under the hood).
97 * Once in PEER state, however, the added capabilities become available; these are on top of
98 * the Session concept API, in the form added members including methods. A quick survey:
99 * - Each of shm::classic::Client_session and shm::classic::Server_session is a shm::classic::Session_mv
100 * (alias and sub-class respectively). shm::classic::Session::session_shm() and
101 * shm::classic::Session::app_shm() each access the pre-made SHM arenas of the aforementioned scopes
102 * (per-session and per-app respectively). Call `construct<T>(...)` on either to SHM-construct an object.
103 * Use an STL-compliant `T` with `Session::Allocator` and shm::stl::Arena_activator aids to store
104 * sophisticated data structures in SHM. Use shm::classic::Session_mv::lend_object() to prepare to
105 * transmit an outer SHM-handle to such a `T` to the opposing shm::classic::Session. On that side use
106 * shm::classic::Session_mv::borrow_object() to recover an equivalent outer SHM-handle. The `T` shall be
107 * returned to the SHM-arena once *both* processes are done with it. The handle acts like a
108 * cross-process-GCing `shared_ptr` (and is, in fact, `shared_ptr<T>`).
109 * - This enables manually-constructing structures and transmitting them from one session participant to the
110 * other.
111 * - On the borrower side one should define `T` in terms of `"Session::Borrower_allocator"` instead of
112 * `"Session::Allocator"`. (With SHM-classic they are the same type; but with arena-lending SHM-providers,
113 * SHM-jemalloc at the moment, they are not.)
114 * - Suppose you have opened a channel C between your two peer objects. Suppose you upgrade it to a
115 * transport::struc::Channel. Without SHM, your only out-of-the-box choice for out-message serialization
116 * is the heap (transport::struc::Channel_base::Serialize_via_heap-tag ctor). This involves copying into
117 * and out of the low-level IPC transport. With SHM you can now do better: as you mutate your out-message,
118 * it will be invisibly backed by SHM-allocated segment(s); and when you `send()` and receive it, only
119 * a small handle will be copied into and out of the IPC transport (again invisibly to you; it'll just happen).
120 * To set it up simply use `transport::struc::Channel_base::Serialize_via_session_shm`-tag
121 * (or possibly `Serialize_via_app_shm`-tag) ctor of `struc::Channel`.
122 * - This enables zero-copy-enabled/arbitrarily-large structured messages through channels in your
123 * shm::classic::Client_session<->shm::classic::Server_session session.
124 *
125 * That's with SHM-classic. With SHM-jemalloc it is all quite similar; basically just replace `classic` with
126 * `arena_lend::jemalloc` in various names above (more or less).
127 * Reminder: it is easiest and most stylish to not have to a big search/replace but rather to use the
128 * top-level alias technique shown in the above code snippets.
129 *
130 * Further details about SHM-classic versus SHM-jemalloc (etc.) are documented elsewhere.
131 * Preview: `arena_lend::jemalloc` is safer and faster (backed by the commercial-grade "jemalloc" `malloc()` impl
132 * algorithm), though it does not allow `app_shm()->construct()` (per-app-scope allocation) on the client side (via
133 * shm::arena_lend::jemalloc::Client_session -- available only shm::arena_lend::jemalloc::Server_session); there's
134 * no such method as `shm::arena_lend::jemalloc::Client_session::app_shm()`.
135 *
136 * ### One more small thing: logging addendum for SHM-arena-lend users ###
137 * This is really a footnote in importance, though there's no good reason to ignore it either.
138 * Certain aspects of SHM-jemalloc (and potentially more future arena-lending-type SHM-providers) require
139 * singleton-based (essentially, global) operation. You need not worry about it... it just works... except
140 * it (like ~all Flow-IPC code) logs; and thus needs to know to which `Logger` to log. Since various ipc::session
141 * objects don't want to presume whose `Logger` is the one to impose on these shared global singletons, we ask
142 * that you do so sometime before any ipc::session::arena_lend object creation.
143 * Namely just do this:
144 *
145 * ~~~
146 * ipc::shm::arena_lend::set_logger(&my_logger); // Before creating sessions.
147 * // ... application runs ...
148 * ipc::shm::arena_lend::set_logger(nullptr); // Before Logger is destroyed.
149 * ~~~
150 *
151 * This fans out to all arena-lend singletons via the `flow::util::Action_registry` mechanism.
152 * If SHM-arena-lend is not used, this call is harmless (no singletons will have registered).
153 *
154 * If you don't, then these particular modules won't log. That could also be fine; but if you are log-enabling
155 * everything else, starting with `Session`s and `Session_server`s in ipc::session, then this equally deserves it.
156 */
157namespace ipc::session::shm
158{
159
160// Types.
161
162// Find doc headers near the bodies of these compound types.
163
164template<typename Arena>
165struct Arena_to_shm_session;
166
167} // namespace ipc::session::shm
ipc::session sub-namespace that groups together facilities for SHM-backed sessions,...
Definition: classic_fwd.hpp:26