Flow-IPC 3.0.0
Flow-IPC project: Full implementation reference.
posix_mq_handle.hpp
Go to the documentation of this file.
1/* Flow-IPC: Core
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#include "ipc/util/util_fwd.hpp"
27#include <flow/log/log.hpp>
28#include <flow/common.hpp>
29#include <mqueue.h>
30
31namespace ipc::transport
32{
33
34// Types.
35
36#ifndef FLOW_OS_LINUX
37static_assert(false, "Posix_mq_handle relies on Linux semantics and has not been tested in other POSIX OS; "
38 "likely does not exist in Windows.");
39#endif
40
41/**
42 * Implements the Persistent_mq_handle concept by wrapping the POSIX message queue API (see `man mq_overview`).
43 *
44 * @see Persistent_mq_handle: implemented concept.
45 *
46 * Reminder: This is available publicly in case it is useful; but it is more likely one would use a
47 * Blob_stream_mq_sender or Blob_stream_mq_receiver which provides a far more convenient boost.asio-like async-capable
48 * API. It uses class(es) like this one in its impl.
49 *
50 * native_handle() returns the underlying MQ descriptor; in Linux (the only OS supported as of this writing)
51 * this happens to be an FD; and as an FD it can (according to `man mq_overview`) participate in `epoll/poll/select()`.
52 * It is simple to wrap this descriptor in a boost.asio `posix::descriptor`. Having done that, one can
53 * `async_wait()` on it, awaiting writability and readability in async fashion not supported by the
54 * Persistent_mq_handle concept. Accordingly Posix_mq_handle::S_HAS_NATIVE_HANDLE is `true`.
55 *
56 * @internal
57 * ### Implementation ###
58 * I (ygoldfel) wrote this immediately after Bipc_mq_handle. Notably the thing that thinly wraps,
59 * `bipc::message_queue`, appears to be heavily influenced by the POSIX MQ API in terms of its API and functionality.
60 * So the implementation here is conceptually similar.
61 */
62class Posix_mq_handle : // Note: movable but not copyable.
63 public flow::log::Log_context
64{
65public:
66 // Constants.
67
68 /// Implements concept API.
70
71 /// Implements concept API. Contrast this value with Bipc_mq_handle::S_HAS_NATIVE_HANDLE.
72 static constexpr bool S_HAS_NATIVE_HANDLE = true;
73
74 // Constructors/destructor.
75
76 /// Implements Persistent_mq_handle API: Construct null handle.
78
79 /**
80 * Implements Persistent_mq_handle API: Construct handle to non-existing named MQ, creating it first. If it already
81 * exists, it is an error.
82 *
83 * `max_n_msg` and `max_msg_sz` are subject to certain OS limits, according to `man mq_overview`. Watch out for
84 * those: we have no control over them here. The `man` page should give you the necessary information.
85 *
86 * @param logger_ptr
87 * See above.
88 * @param absolute_name
89 * See above.
90 * @param mode_tag
91 * See above.
92 * @param perms
93 * See above.
94 * Reminder: Suggest the use of util::shared_resource_permissions() to translate
95 * from one of a small handful of levels of access; these apply almost always in practice.
96 * @param max_n_msg
97 * See above.
98 * @param max_msg_sz
99 * See above.
100 * @param err_code
101 * See above.
102 */
103 explicit Posix_mq_handle(flow::log::Logger* logger_ptr, const Shared_name& absolute_name,
104 util::Create_only mode_tag, size_t max_n_msg, size_t max_msg_sz,
105 const util::Permissions& perms = {}, Error_code* err_code = nullptr);
106 /**
107 * Implements Persistent_mq_handle API: Construct handle to existing named MQ, or else if it does not exist creates
108 * it first and opens it (atomically).
109 *
110 * @param logger_ptr
111 * See above.
112 * @param absolute_name
113 * See above.
114 * @param mode_tag
115 * See above.
116 * @param perms_on_create
117 * See above.
118 * Reminder: Suggest the use of util::shared_resource_permissions() to translate
119 * from one of a small handful of levels of access; these apply almost always in practice.
120 * @param max_n_msg_on_create
121 * See above.
122 * @param max_msg_sz_on_create
123 * See above.
124 * @param err_code
125 * See above.
126 */
127 explicit Posix_mq_handle(flow::log::Logger* logger_ptr, const Shared_name& absolute_name,
128 util::Open_or_create mode_tag, size_t max_n_msg_on_create, size_t max_msg_sz_on_create,
129 const util::Permissions& perms_on_create = {}, Error_code* err_code = nullptr);
130 /**
131 * Implements Persistent_mq_handle API: Construct handle to existing named MQ. If it does not exist, it is an error.
132 *
133 * @param logger_ptr
134 * See above.
135 * @param absolute_name
136 * See above.
137 * @param mode_tag
138 * See above.
139 * @param err_code
140 * See above.
141 */
142 explicit Posix_mq_handle(flow::log::Logger* logger_ptr, const Shared_name& absolute_name,
143 util::Open_only mode_tag, Error_code* err_code = nullptr);
144
145 /**
146 * Implements Persistent_mq_handle API: Constructs handle from the source handle while making the latter as-if
147 * default-cted. Reminder, informally: This is a light-weight op.
148 *
149 * @param src
150 * See above.
151 */
153
154 /// Copying of handles is prohibited, per Persistent_mq_handle concept.
156
157 /**
158 * Implements Persistent_mq_handle API: Destroys this handle (or no-op if no handle was successfully constructed, or
159 * if it's a moved-from or default-cted handle). Reminder: The underlying MQ (if any) is *not* destroyed and can
160 * be attached-to by another handle.
161 */
163
164 // Methods.
165
166 /**
167 * Implements Persistent_mq_handle API: Replaces handle with the source handle while making the latter invalid as-if
168 * default-cted. Reminder, informally: this is a light-weight op.
169 *
170 * @param src
171 * See above.
172 * @return `*this`.
173 */
175
176 /// Copying of handles is prohibited, per Persistent_mq_handle concept.
178
179 /**
180 * Implements Persistent_mq_handle API: Removes the named persistent MQ. Reminder: name is removed immediately
181 * (if present -- otherwise error), but underlying MQ continues to exist until all system-wide handles to it
182 * are closed.
183 *
184 * @see Reminder: see also `util::remove_each_persistent_*()`.
185 *
186 * @param logger_ptr
187 * See above.
188 * @param name
189 * See above.
190 * @param err_code
191 * See above.
192 */
193 static void remove_persistent(flow::log::Logger* logger_ptr, const Shared_name& name, Error_code* err_code = nullptr);
194
195 /**
196 * Implements Persistent_mq_handle API. Impl note for exposition: we use the fact that, e.g., in Linux
197 * the POSIX MQ devices are listed in flat fashion in `/dev/mqueue`.
198 *
199 * @tparam Handle_name_func
200 * See above.
201 * @param handle_name_func
202 * See above.
203 */
204 template<typename Handle_name_func>
205 static void for_each_persistent(const Handle_name_func& handle_name_func);
206
207 /**
208 * Implements Persistent_mq_handle API: Non-blocking send: pushes copy of message to queue and returns `true`;
209 * if queue is full then no-op and returns `false`.
210 *
211 * ### INFO+ logging ###
212 * WARNING on error. (You may use the `flow::log::Config::this_thread_verbosity_override_auto()` to
213 * temporarily, in that thread only, disable/reduce logging. This is quite easy and performant.)
214 *
215 * @param blob
216 * See above.
217 * @param err_code
218 * See above.
219 * @return See above.
220 */
221 bool try_send(const util::Blob_const& blob, Error_code* err_code = nullptr);
222
223 /**
224 * Implements Persistent_mq_handle API: Blocking send: pushes copy of message to queue; if queue is full blocks
225 * until it is not.
226 *
227 * ### INFO+ logging ###
228 * WARNING on error. (You may use the `flow::log::Config::this_thread_verbosity_override_auto()`
229 * to temporarily, in that thread only, disable/reduce logging. This is quite easy and performant.)
230 *
231 * @param blob
232 * See above.
233 * @param err_code
234 * See above.
235 */
236 void send(const util::Blob_const& blob, Error_code* err_code = nullptr);
237
238 /**
239 * Implements Persistent_mq_handle API: Blocking timed send: pushes copy of message to queue; if queue is full
240 * blocks until it is not, or the specified time passes, whichever happens first.
241 *
242 * ### INFO+ logging ###
243 * WARNING on error or timed out.
244 * (You may use the `flow::log::Config::this_thread_verbosity_override_auto()` to
245 * temporarily, in that thread only, disable/reduce logging. This is quite easy and performant.)
246 *
247 * @param blob
248 * See above.
249 * @param timeout_from_now
250 * See above.
251 * @param err_code
252 * See above.
253 * @return See above.
254 */
255 bool timed_send(const util::Blob_const& blob, util::Fine_duration timeout_from_now, Error_code* err_code = nullptr);
256
257 /**
258 * Implements Persistent_mq_handle API: Like try_send() but without the actual pushing of a message.
259 *
260 * ### INFO+ logging ###
261 * WARNING on error.
262 *
263 * @param err_code
264 * See above.
265 * @return See above.
266 */
267 bool is_sendable(Error_code* err_code = nullptr);
268
269 /**
270 * Implements Persistent_mq_handle API: Like send() but without the actual pushing of a message.
271 *
272 * ### INFO+ logging ###
273 * WARNING on error.
274 *
275 * @param err_code
276 * See above.
277 */
278 void wait_sendable(Error_code* err_code = nullptr);
279
280 /**
281 * Implements Persistent_mq_handle API: Like timed_send() but without the actual pushing of a message.
282 *
283 * ### INFO+ logging ###
284 * WARNING on error.
285 *
286 * @param timeout_from_now
287 * See above.
288 * @param err_code
289 * See above.
290 * @return See above.
291 */
292 bool timed_wait_sendable(util::Fine_duration timeout_from_now, Error_code* err_code = nullptr);
293
294 /**
295 * Implements Persistent_mq_handle API: Non-blocking receive: pops copy of message from queue into buffer and
296 * returns `true`; if queue is empty then no-op and returns `false`.
297 *
298 * ### INFO+ logging ###
299 * WARNING on error. (You may use the `flow::log::Config::this_thread_verbosity_override_auto()` to
300 * temporarily, in that thread only, disable/reduce logging. This is quite easy and performant.)
301 *
302 * @param blob
303 * See above.
304 * @param err_code
305 * See above.
306 * @return See above.
307 */
308 bool try_receive(util::Blob_mutable* blob, Error_code* err_code = nullptr);
309
310 /**
311 * Implements Persistent_mq_handle API: Blocking receive: pops copy of message from queue into buffer; if queue
312 * is empty blocks until it is not.
313 *
314 * ### INFO+ logging ###
315 * WARNING on error. (You may use the `flow::log::Config::this_thread_verbosity_override_auto()` to
316 * temporarily, in that thread only, disable/reduce logging. This is quite easy and performant.)
317 *
318 * @param blob
319 * See above.
320 * @param err_code
321 * See above.
322 */
323 void receive(util::Blob_mutable* blob, Error_code* err_code = nullptr);
324
325 /**
326 * Implements Persistent_mq_handle API: Blocking timed receive: pops copy of message from queue into buffer;
327 * if queue is empty blocks until it is not, or the specified time passes, whichever happens first.
328 *
329 * ### INFO+ logging ###
330 * WARNING on error or timed out. (You may use the `flow::log::Config::this_thread_verbosity_override_auto()` to
331 * temporarily, in that thread only, disable/reduce logging. This is quite easy and performant.)
332 *
333 * @param blob
334 * See above.
335 * @param timeout_from_now
336 * See above.
337 * @param err_code
338 * See above.
339 * @return See above.
340 */
341 bool timed_receive(util::Blob_mutable* blob, util::Fine_duration timeout_from_now, Error_code* err_code = nullptr);
342
343 /**
344 * Implements Persistent_mq_handle API: Like try_receive() but without the actual popping of a message.
345 *
346 * ### INFO+ logging ###
347 * WARNING on error.
348 *
349 * @param err_code
350 * See above.
351 * @return See above.
352 */
353 bool is_receivable(Error_code* err_code = nullptr);
354
355 /**
356 * Implements Persistent_mq_handle API: Like receive() but without the actual popping of a message.
357 *
358 * ### INFO+ logging ###
359 * WARNING on error.
360 *
361 * @param err_code
362 * See above.
363 */
364 void wait_receivable(Error_code* err_code = nullptr);
365
366 /**
367 * Implements Persistent_mq_handle API: Like timed_receive() but without the actual popping of a message.
368 *
369 * ### INFO+ logging ###
370 * WARNING on error.
371 *
372 * @param timeout_from_now
373 * See above.
374 * @param err_code
375 * See above.
376 * @return See above.
377 */
378 bool timed_wait_receivable(util::Fine_duration timeout_from_now, Error_code* err_code = nullptr);
379
380 /**
381 * Implements Persistent_mq_handle API:
382 * Turn on preemptive/concurrent interruption of blocking-sends and sendable-waits/polls.
383 *
384 * ### INFO+ logging ###
385 * WARNING on duplicate use, INFO otherwise.
386 *
387 * @return See above.
388 */
389 bool interrupt_sends();
390
391 /**
392 * Implements Persistent_mq_handle API:
393 * Turn off preemptive/concurrent interruption of blocking-sends and sendable-waits/polls.
394 *
395 * ### INFO+ logging ###
396 * WARNING on duplicate use, INFO otherwise.
397 *
398 * @return See above.
399 */
400 bool allow_sends();
401
402 /**
403 * Implements Persistent_mq_handle API:
404 * Turn on preemptive/concurrent interruption of blocking-receives and receivable-waits/polls.
405 *
406 * ### INFO+ logging ###
407 * WARNING on duplicate use, INFO otherwise.
408 *
409 * @return See above.
410 */
411 bool interrupt_receives();
412
413 /**
414 * Implements Persistent_mq_handle API:
415 * Turn off preemptive/concurrent interruption of blocking-receives and receivable-waits/polls.
416 *
417 * ### INFO+ logging ###
418 * WARNING on duplicate use, INFO otherwise.
419 *
420 * @return See above.
421 */
422 bool allow_receives();
423
424 /**
425 * Implements Persistent_mq_handle API: Returns name equal to `absolute_name` passed to ctor.
426 * @return See above.
427 */
428 const Shared_name& absolute_name() const;
429
430 /**
431 * Implements Persistent_mq_handle API: Returns the max message size of the underlying queue. Reminder:
432 * This is not required to match what was passed to `Create_only` or `Open_or_create` ctor.
433 *
434 * @return See above.
435 */
436 size_t max_msg_size() const;
437
438 /**
439 * Implements Persistent_mq_handle API: Returns the max message count of the underlying queue. Reminder:
440 * This is not required to match what was passed to `Create_only` or `Open_or_create` ctor.
441 *
442 * @return See above.
443 */
444 size_t max_n_msgs() const;
445
446 /**
447 * Implements Persistent_mq_handle API: Returns the stored native MQ handle; null if not open.
448 *
449 * @return See above.
450 */
452
453private:
454 // Types.
455
456 /// Short-hand for anonymous pipe write end.
458
459 /// Short-hand for anonymous pipe read end.
461
462 // Friends.
463
464 // Friend of Posix_mq_handle.
465 friend void swap(Posix_mq_handle& val1, Posix_mq_handle& val2);
466
467 // Constructors/destructor.
468
469 /**
470 * Helper ctor delegated by the 2 `public` ctors that take `Open_or_create` or `Create_only` mode.
471 *
472 * @tparam Mode_tag
473 * Either util::Open_or_create or util::Create_only.
474 * @param logger_ptr
475 * See `public` ctors.
476 * @param absolute_name
477 * See `public` ctors.
478 * @param mode_tag
479 * See `public` ctors.
480 * @param max_n_msg_on_create
481 * See `public` ctors.
482 * @param max_msg_sz_on_create
483 * See `public` ctors.
484 * @param perms_on_create
485 * See `public` ctors.
486 * @param err_code
487 * See `public` ctors.
488 */
489 template<typename Mode_tag>
490 explicit Posix_mq_handle(Mode_tag mode_tag, flow::log::Logger* logger_ptr, const Shared_name& absolute_name,
491 size_t max_n_msg_on_create, size_t max_msg_sz_on_create,
492 const util::Permissions& perms_on_create,
493 Error_code* err_code);
494
495 // Methods.
496
497 /**
498 * Ctor helper that sets up `m_interrupt*` pipe items. If (and only if) it fails it returns truthy code but performs
499 * no cleanup of any resources including the ones it may have part-setup. That is caller's responsibility.
500 *
501 * @return See above.
502 */
504
505 /**
506 * Ctor helper that sets up #m_epoll_hndl_snd and #m_epoll_hndl_rcv. If (and only if) it fails it returns truthy
507 * code but performs no cleanup of any resources including the ones it may have part-setup. That is caller's
508 * responsibility.
509 *
510 * @return See above.
511 */
513
514 /**
515 * Sets #m_mq to blocking or non-blocking and returns `true` on success and clears `*err_code`; otherwise returns
516 * `false` and sets truthy `*err_code`.
517 *
518 * @param err_code
519 * To set. If null behavior is undefined (assertion may trip).
520 * @param nb
521 * Non-blocking if `true`, else blocking.
522 * @return `true` <=> success.
523 */
524 bool set_non_blocking(bool nb, Error_code* err_code);
525
526 /**
527 * Helper that handles the result of an `mq_*()` call by logging WARNING(s) on error; setting `*err_code` on error;
528 * clearing it on success. `errno` is presumably set by the native API on error going into this.
529 *
530 * @param result
531 * What the native API returned.
532 * @param err_code
533 * To set. If null behavior is undefined (assertion may trip).
534 * @param context
535 * See Bipc_mq_handle::op_with_possible_bipc_mq_exception().
536 * @return `true` if `*err_code` was set to success (falsy); else `false` (it was set to truthy).
537 */
538 bool handle_mq_api_result(int result, Error_code* err_code, util::String_view context) const;
539
540 /**
541 * Impl body for `interrupt_*()`.
542 *
543 * @tparam SND_ELSE_RCV
544 * True for `*_sends()`, else `*_receives()`.
545 * @return See callers.
546 */
547 template<bool SND_ELSE_RCV>
548 bool interrupt_impl();
549
550 /**
551 * Impl body for `allow_*()`.
552 *
553 * @tparam SND_ELSE_RCV
554 * True for `*_sends()`, else `*_receives()`.
555 * @return See callers.
556 */
557 template<bool SND_ELSE_RCV>
558 bool allow_impl();
559
560 /**
561 * Impl body for `*_sendable()` and `*_receivable()`.
562 *
563 * @tparam SND_ELSE_RCV
564 * True for `*_sendable()`, else `*_receivable()`.
565 * @param timeout_from_now_or_none
566 * `timeout_from_now`; or 0 for `is_*()`, or `Fine_duration::max()` for non-timed-blocking variant.
567 * @param err_code
568 * See callers.
569 * @return See callers.
570 */
571 template<bool SND_ELSE_RCV>
572 bool wait_impl(util::Fine_duration timeout_from_now_or_none, Error_code* err_code);
573
574 // Data.
575
576 /**
577 * Underlying MQ handle. We are a thin wrapper around this really. `.null()` if creation
578 * fails in ctor, or if `*this` was moved-from. This is very light-weight; probably `int`.
579 */
581
582 /// See absolute_name().
584
585 /**
586 * `epoll_*()` handle (`.null()` if and only if #m_mq is null) that is level-triggered to be active
587 * (with only 1 event registered) if and only if #m_mq is currently capable of sending at least 1 message
588 * (we could push 1+ messages right now). Used by wait_impl() and its various public `*_sendable()` forms.
589 */
591
592 /**
593 * `epoll_*()` handle (`.null()` if and only if #m_mq is null) that is level-triggered to be active
594 * (with only 1 event registered) if and only if #m_mq is currently storing at least 1 message
595 * (we could pop 1+ messages right now). Used by wait_impl() and its various public `*_receivable()` forms.
596 */
598
599 /**
600 * Starting at `false`, this is made `true` via interrupt_sends(), and back by allow_sends(); acts as a guard
601 * against doing it when already in effect. Note that that is its only purpose; as wait_impl() never checks it;
602 * instead it relies on `epoll_wait()` detecting a readable #m_interrupt_detector_snd.
603 */
605
606 /// Other-direction counterpart to #m_interrupting_snd.
608
609 /// Never used for `.run()` or `.async()` -- just so we can construct #Pipe_reader, #Pipe_writer.
610 flow::util::Task_engine m_nb_task_engine;
611
612 /**
613 * A byte is written to this end by interrupt_sends() to make it readable for the poll-wait in wait_impl()
614 * indicating that #m_interrupting_snd mode is on.
615 */
617
618 /**
619 * A byte is read from this end by allow_sends() to make it not-readable for the poll-wait in wait_impl()
620 * indicating that #m_interrupting_snd mode is off; and wait_impl() poll-waits on this along with
621 * #m_mq -- if it is readable, then the mode is on.
622 */
624
625 /// Other-direction counterpart to #m_interrupter_snd.
627
628 /// Other-direction counterpart to #m_interrupt_detector_snd.
630}; // class Posix_mq_handle
631
632// Free functions: in *_fwd.hpp.
633
634// Template implementations.
635
636template<typename Handle_name_func>
637void Posix_mq_handle::for_each_persistent(const Handle_name_func& handle_name_func) // Static.
638{
639#ifndef FLOW_OS_LINUX
640 static_assert(false, "This method relies on/has been tested only with Linux /dev/mqueue semantics.");
641#endif
642 util::for_each_persistent_impl("/dev/mqueue", handle_name_func);
643}
644
645} // namespace ipc::transport
Implements the Persistent_mq_handle concept by wrapping the POSIX message queue API (see man mq_overv...
bool allow_sends()
Implements Persistent_mq_handle API: Turn off preemptive/concurrent interruption of blocking-sends an...
bool interrupt_receives()
Implements Persistent_mq_handle API: Turn on preemptive/concurrent interruption of blocking-receives ...
bool timed_wait_sendable(util::Fine_duration timeout_from_now, Error_code *err_code=nullptr)
Implements Persistent_mq_handle API: Like timed_send() but without the actual pushing of a message.
bool interrupt_sends()
Implements Persistent_mq_handle API: Turn on preemptive/concurrent interruption of blocking-sends and...
util::Pipe_reader Pipe_reader
Short-hand for anonymous pipe read end.
bool timed_wait_receivable(util::Fine_duration timeout_from_now, Error_code *err_code=nullptr)
Implements Persistent_mq_handle API: Like timed_receive() but without the actual popping of a message...
static const Shared_name S_RESOURCE_TYPE_ID
Implements concept API.
bool wait_impl(util::Fine_duration timeout_from_now_or_none, Error_code *err_code)
Impl body for *_sendable() and *_receivable().
static void for_each_persistent(const Handle_name_func &handle_name_func)
Implements Persistent_mq_handle API.
void receive(util::Blob_mutable *blob, Error_code *err_code=nullptr)
Implements Persistent_mq_handle API: Blocking receive: pops copy of message from queue into buffer; i...
bool try_send(const util::Blob_const &blob, Error_code *err_code=nullptr)
Implements Persistent_mq_handle API: Non-blocking send: pushes copy of message to queue and returns t...
bool handle_mq_api_result(int result, Error_code *err_code, util::String_view context) const
Helper that handles the result of an mq_*() call by logging WARNING(s) on error; setting *err_code on...
Pipe_reader m_interrupt_detector_snd
A byte is read from this end by allow_sends() to make it not-readable for the poll-wait in wait_impl(...
void wait_receivable(Error_code *err_code=nullptr)
Implements Persistent_mq_handle API: Like receive() but without the actual popping of a message.
Native_handle m_epoll_hndl_snd
epoll_*() handle (.null() if and only if m_mq is null) that is level-triggered to be active (with onl...
bool allow_receives()
Implements Persistent_mq_handle API: Turn off preemptive/concurrent interruption of blocking-receives...
size_t max_msg_size() const
Implements Persistent_mq_handle API: Returns the max message size of the underlying queue.
Pipe_reader m_interrupt_detector_rcv
Other-direction counterpart to m_interrupt_detector_snd.
Error_code epoll_setup()
Ctor helper that sets up m_epoll_hndl_snd and m_epoll_hndl_rcv.
util::Pipe_writer Pipe_writer
Short-hand for anonymous pipe write end.
size_t max_n_msgs() const
Implements Persistent_mq_handle API: Returns the max message count of the underlying queue.
void wait_sendable(Error_code *err_code=nullptr)
Implements Persistent_mq_handle API: Like send() but without the actual pushing of a message.
Pipe_writer m_interrupter_rcv
Other-direction counterpart to m_interrupter_snd.
Native_handle native_handle() const
Implements Persistent_mq_handle API: Returns the stored native MQ handle; null if not open.
friend void swap(Posix_mq_handle &val1, Posix_mq_handle &val2)
Implements Persistent_mq_handle related concept: Swaps two objects.
bool try_receive(util::Blob_mutable *blob, Error_code *err_code=nullptr)
Implements Persistent_mq_handle API: Non-blocking receive: pops copy of message from queue into buffe...
Posix_mq_handle()
Implements Persistent_mq_handle API: Construct null handle.
bool m_interrupting_snd
Starting at false, this is made true via interrupt_sends(), and back by allow_sends(); acts as a guar...
Posix_mq_handle(const Posix_mq_handle &)=delete
Copying of handles is prohibited, per Persistent_mq_handle concept.
const Shared_name & absolute_name() const
Implements Persistent_mq_handle API: Returns name equal to absolute_name passed to ctor.
void send(const util::Blob_const &blob, Error_code *err_code=nullptr)
Implements Persistent_mq_handle API: Blocking send: pushes copy of message to queue; if queue is full...
Native_handle m_epoll_hndl_rcv
epoll_*() handle (.null() if and only if m_mq is null) that is level-triggered to be active (with onl...
Posix_mq_handle & operator=(const Posix_mq_handle &)=delete
Copying of handles is prohibited, per Persistent_mq_handle concept.
bool allow_impl()
Impl body for allow_*().
bool interrupt_impl()
Impl body for interrupt_*().
bool timed_send(const util::Blob_const &blob, util::Fine_duration timeout_from_now, Error_code *err_code=nullptr)
Implements Persistent_mq_handle API: Blocking timed send: pushes copy of message to queue; if queue i...
~Posix_mq_handle()
Implements Persistent_mq_handle API: Destroys this handle (or no-op if no handle was successfully con...
bool is_sendable(Error_code *err_code=nullptr)
Implements Persistent_mq_handle API: Like try_send() but without the actual pushing of a message.
bool timed_receive(util::Blob_mutable *blob, util::Fine_duration timeout_from_now, Error_code *err_code=nullptr)
Implements Persistent_mq_handle API: Blocking timed receive: pops copy of message from queue into buf...
bool set_non_blocking(bool nb, Error_code *err_code)
Sets m_mq to blocking or non-blocking and returns true on success and clears *err_code; otherwise ret...
Shared_name m_absolute_name
See absolute_name().
static void remove_persistent(flow::log::Logger *logger_ptr, const Shared_name &name, Error_code *err_code=nullptr)
Implements Persistent_mq_handle API: Removes the named persistent MQ.
Error_code pipe_setup()
Ctor helper that sets up m_interrupt* pipe items.
bool m_interrupting_rcv
Other-direction counterpart to m_interrupting_snd.
bool is_receivable(Error_code *err_code=nullptr)
Implements Persistent_mq_handle API: Like try_receive() but without the actual popping of a message.
Pipe_writer m_interrupter_snd
A byte is written to this end by interrupt_sends() to make it readable for the poll-wait in wait_impl...
Native_handle m_mq
Underlying MQ handle.
flow::util::Task_engine m_nb_task_engine
Never used for .run() or .async() – just so we can construct Pipe_reader, Pipe_writer.
Posix_mq_handle & operator=(Posix_mq_handle &&src)
Implements Persistent_mq_handle API: Replaces handle with the source handle while making the latter i...
static constexpr bool S_HAS_NATIVE_HANDLE
Implements concept API. Contrast this value with Bipc_mq_handle::S_HAS_NATIVE_HANDLE.
String-wrapping abstraction representing a name uniquely distinguishing a kernel-persistent entity fr...
Flow-IPC module providing transmission of structured messages and/or low-level blobs (and more) betwe...
util::Shared_name Shared_name
Convenience alias for the commonly used type util::Shared_name.
bipc::permissions Permissions
Short-hand for Unix (POSIX) permissions class.
Definition: util_fwd.hpp:158
bipc::open_only_t Open_only
Tag type indicating an ideally-atomic open-if-exists-else-fail operation.
Definition: util_fwd.hpp:152
void for_each_persistent_impl(const fs::path &persistent_obj_dev_dir_path, const Handle_name_func &handle_name_func)
Implementation of Persistent_object::for_each_persistent(); for example see shm::classic::Pool_arena:...
Definition: util.hpp:91
boost::asio::mutable_buffer Blob_mutable
Short-hand for a mutable blob somewhere in memory, stored as exactly a void* and a size_t.
Definition: util_fwd.hpp:137
boost::asio::writable_pipe Pipe_writer
Short-hand for anonymous pipe write end.
Definition: util_fwd.hpp:35
bipc::open_or_create_t Open_or_create
Tag type indicating an atomic open-if-exists-else-create operation.
Definition: util_fwd.hpp:149
bipc::create_only_t Create_only
Tag type indicating a create-unless-exists-else-fail operation.
Definition: util_fwd.hpp:155
boost::asio::readable_pipe Pipe_reader
Short-hand for anonymous pipe read end.
Definition: util_fwd.hpp:38
flow::Fine_duration Fine_duration
Short-hand for Flow's Fine_duration.
Definition: util_fwd.hpp:114
boost::asio::const_buffer Blob_const
Short-hand for an immutable blob somewhere in memory, stored as exactly a void const * and a size_t.
Definition: util_fwd.hpp:131
flow::util::String_view String_view
Short-hand for Flow's String_view.
Definition: util_fwd.hpp:112
flow::Error_code Error_code
Short-hand for flow::Error_code which is very common.
Definition: common.hpp:313
A monolayer-thin wrapper around a native handle, a/k/a descriptor a/k/a FD.