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