Flow-IPC 1.0.0
Flow-IPC project: Full implementation reference.
client_session_adapter.hpp
Go to the documentation of this file.
1/* Flow-IPC: Sessions
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
24{
25
26// Types.
27
28/**
29 * `sync_io`-pattern counterpart to async-I/O-pattern session::Client_session types and all their SHM-aware variations
30 * (at least shm::classic::Client_session et al and shm::arena_lend::jemalloc::Client_session et al). In point of fact:
31 * - Use this if and only if you desire a `sync_io`-pattern style of being informed of async events from a
32 * `Client_session` of any kind. For example, you may find this convenient if your event loop is an old-school
33 * reactor using `poll()` or `epoll_wait()`. This affects exactly the following APIs:
34 * - `Client_session` reporting a session-hosing error via on-error handler.
35 * - Set up via ctor.
36 * - `Client_session` reporting a channel having been passively-opened via that handler.
37 * - Set up via ctor.
38 * - This Client_session_adapter *adapts* a `Client_session` constructed and stored within `*this`.
39 * All APIs excluding the above -- that is to say all non-async APIs -- are to be invoked via core() accessor.
40 *
41 * @see util::sync_io doc header -- describes the general `sync_io` pattern we are following.
42 * @see session::Client_session_mv, session::Client_session, et al.
43 *
44 * As is generally the case when choosing `sync_io::X` versus `X`, we recommend using `X` due to it being easier.
45 * In this particular case (see below) there is no perf benefit to using `sync_io::X`, either, so the only reason
46 * to use `sync_io::X` in this case would be because you've got an old-school reactor event loop with
47 * a `poll()` or `epoll_wait()`, in which case the `sync_io` API may be easier to integrate.
48 *
49 * To use it:
50 * - Construct it explicitly. As with an async-I/O `Client_session` you will need to provide:
51 * - Error handler (though it will be invoked synchronously per `sync_io` pattern).
52 * - (Optional -- if you want to enable channel passive-open): Channel passive-open handler
53 * (though it will be invoked via... ditto).
54 * - Set up `sync_io` pattern using start_ops() (and if needed precede it with replace_event_wait_handles()).
55 * - Use `core->sync_connect()` in identical fashion to async-I/O `Client_session`.
56 * - On successful connect:
57 * - Be ready for error handler to fire (in `sync_io` style).
58 * - Be ready for passive-channel-open handler to fire (in `sync_io` style).
59 * - Use `core()->` for all other API needs (e.g., `open_channel()`, `session_shm()` -- if SHM-aware).
60 *
61 * ### Internal implementation ###
62 * Normally this would not be in the public docs for this public-use class, but indulge us.
63 *
64 * In perf-critical situations, such as the various transport::Blob_sender / transport::Blob_receiver / etc.
65 * impls, typically `sync_io::X` contains the core implementation, then `X` adapts a `sync_io::X` *core*
66 * to provide background-thread-driven work and signaling of completion. We do not consider
67 * the present `X = Client_session` to be perf-critical; as such the present `sync_io::X` adapts
68 * the `X`. Internally this is accomplished using an unnamed IPC-pipe, where
69 * an internal background thread W tickles said IPC-pipe which is waited-on by the user of
70 * sync_io::Client_session_adapter.
71 *
72 * @todo Make all of Server_session_adapter, Client_session_adapter move-ctible/assignable like their adapted
73 * counterparts. It is not of utmost importance practically, unlike for the adapter guys, but at least for
74 * consistency it would be good; and of course it never hurts usability even if not critical.
75 * (Internally: This is not difficult to implement; the async-I/O guys being movable was really the hard part.)
76 *
77 * @tparam Session
78 * The async-I/O `Client_session` concrete type being adapted. As of this writing that would be one of
79 * at least: `session::Client_session<knobs>`, `session::shm::classic::Client_session<knobs>`,
80 * `session::shm::jemalloc::Client_session<knobs>`.
81 */
82template<typename Session>
84 private Session_adapter<Session>,
85 private boost::noncopyable // There's a to-do to make it movable.
86{
87private:
88 // Types.
89
90 /// Our main base.
92
93public:
94 // Types.
95
96 /// Short-hand, for generic programming et al, for template parameter `Session`.
98
99 /// Useful for generic programming, the async-I/O-pattern counterpart to `*this` type.
101 /// You may disregard.
103
104 // Constructors/destructor.
105
106 /**
107 * Forwards to the #Session_obj ctor. See Client_session_mv ctor doc headers.
108 *
109 * @tparam Ctor_args
110 * See above.
111 * @param ctor_args
112 * See above.
113 */
114 template<typename... Ctor_args>
115 Client_session_adapter(Ctor_args&&... ctor_args);
116
117 // Methods.
118
119 /**
120 * Sets up the `sync_io`-pattern interaction between `*this` and the user's event loop; required before
121 * `*this` will do any work.
122 *
123 * `ev_wait_func()` -- with signature matching util::sync_io::Event_wait_func -- is a key function memorized
124 * by `*this`. It shall be invoked by `*this` operations when some op cannot complete synchronously and requires
125 * a certain event (readable/writable) to be active on a certain native-handle.
126 *
127 * @see util::sync_io::Event_wait_func doc header for useful and complete instructions on how to write an
128 * `ev_wait_func()` properly. Doing so correctly is the crux of using the `sync_io` pattern.
129 *
130 * This is a standard `sync_io`-pattern API per util::sync_io doc header.
131 *
132 * @tparam Event_wait_func_t
133 * Function type matching util::sync_io::Event_wait_func.
134 * @param ev_wait_func
135 * See above.
136 * @return `false` if this has already been invoked; no-op logging aside. `true` otherwise.
137 */
138 template<typename Event_wait_func_t>
139 bool start_ops(Event_wait_func_t&& ev_wait_func);
140
141 /**
142 * Analogous to transport::sync_io::Native_handle_sender::replace_event_wait_handles().
143 *
144 * @tparam Create_ev_wait_hndl_func
145 * See above.
146 * @param create_ev_wait_hndl_func
147 * See above.
148 * @return See above.
149 */
150 template<typename Create_ev_wait_hndl_func>
151 bool replace_event_wait_handles(const Create_ev_wait_hndl_func& create_ev_wait_hndl_func);
152
153 /**
154 * The adapted mutable #Session_obj. It is safe to access any non-async API; that is to say all of them as of
155 * this writing. Remember that start_ops() is required before `core()->sync_connect()` however.
156 *
157 * @return See above.
158 */
159 Session_obj* core();
160
161 /**
162 * The adapted immutable #Session_obj. Remember that start_ops() is required before `core()->sync_connect()` however.
163 *
164 * @return See above.
165 */
166 const Session_obj* core() const;
167
168 // The LOG_*() macros don't see Log_context::get_log*() from base otherwise....
169 using Base::get_logger;
171}; // class Client_session_adapter
172
173// Free functions: in *_fwd.hpp.
174
175// Template implementations.
176
177template<typename Session>
178template<typename... Ctor_args>
180 Base(std::forward<Ctor_args>(ctor_args)...)
181{
182 // That's all.
183}
184
185template<typename Session>
186template<typename Event_wait_func_t>
187bool Client_session_adapter<Session>::start_ops(Event_wait_func_t&& ev_wait_func)
188{
189 return Base::start_ops(std::move(ev_wait_func));
190} // Session_adapter::start_ops()
191
192template<typename Session>
193template<typename Create_ev_wait_hndl_func>
194bool
195 Client_session_adapter<Session>::replace_event_wait_handles(const Create_ev_wait_hndl_func& create_ev_wait_hndl_func)
196{
197 return Base::replace_event_wait_handles(create_ev_wait_hndl_func);
198}
199
200template<typename Session>
203{
204 return Base::core();
205}
206
207template<typename Session>
210{
211 return const_cast<Client_session_adapter*>(this)->core();
212}
213
214template<typename Session>
215std::ostream& operator<<(std::ostream& os,
217{
218 return os << "SIO@" << static_cast<const void*>(&val) << " cli_sess[" << (*(val.core())) << ']';
219}
220
221} // namespace ipc::session::sync_io
sync_io-pattern counterpart to async-I/O-pattern session::Client_session types and all their SHM-awar...
typename Base::Session_obj Session_obj
Short-hand, for generic programming et al, for template parameter Session.
bool start_ops(Event_wait_func_t &&ev_wait_func)
Sets up the sync_io-pattern interaction between *this and the user's event loop; required before *thi...
Session_obj * core()
The adapted mutable Session_obj.
typename Base::Async_io_obj Async_io_obj
Useful for generic programming, the async-I/O-pattern counterpart to *this type.
typename Base::Sync_io_obj Sync_io_obj
You may disregard.
bool replace_event_wait_handles(const Create_ev_wait_hndl_func &create_ev_wait_hndl_func)
Analogous to transport::sync_io::Native_handle_sender::replace_event_wait_handles().
Client_session_adapter(Ctor_args &&... ctor_args)
Forwards to the Session_obj ctor.
Internal-use workhorse containing common elements of Client_session_adapter and Server_session_adapte...
const flow::log::Component & get_log_component() const
See flow::log::Log_context.
transport::Null_peer Sync_io_obj
See, e.g., Client_session_adapter.
flow::log::Logger * get_logger() const
See flow::log::Log_context.
Session Session_obj
See, e.g., Client_session_adapter.
Session_obj Async_io_obj
See, e.g., Client_session_adapter.
sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::session.
std::ostream & operator<<(std::ostream &os, const Server_session_adapter< Session > &val)
Prints string representation of the given Server_session_adapter to the given ostream.