26#include "ipc/transport/struc/shm/schema/detail/serialization.capnp.h"
27#include <boost/interprocess/containers/list.hpp>
65template<
typename Shm_arena>
68 public flow::log::Log_context
210 kj::ArrayPtr<::capnp::word>
allocateSegment(
unsigned int min_sz)
override;
241template<
typename Shm_arena>
243 (flow::log::Logger* logger_ptr,
Arena* arena) :
245 flow::log::Log_context(logger_ptr,
Log_component::S_TRANSPORT),
248 m_segment_sz(::
capnp::SUGGESTED_FIRST_SEGMENT_WORDS * sizeof(::
capnp::word)),
250 m_serialization_segments(m_arena->template construct<
Segments_in_shm>())
252 FLOW_LOG_TRACE(
"SHM builder [" << *
this <<
"]: Created.");
255template<
typename Shm_arena>
258 FLOW_LOG_TRACE(
"SHM builder [" << *
this <<
"]: Destroyed. The following may SHM-dealloc the serialization, "
259 "if recipient was done with it before us, or if we hadn't done lend() yet.");
263template<
typename Shm_arena>
269 using flow::util::buffers_dump_string;
294 assert((!blobs.empty())
295 &&
"Should not be possible for serialization to be empty with our use cases. Investigate.");
297 const auto capnp_segs = getSegmentsForOutput();
298 assert((capnp_segs.size() == blobs.size())
299 &&
"Somehow our MessageBuilder created fewer or more segments than allocateSegment() was called?!");
302 typename Segments_in_shm::iterator blob_it;
303 for (idx = 0, blob_it = blobs.begin(); idx != capnp_segs.size(); ++idx, ++blob_it)
305 const auto capnp_seg = capnp_segs[idx].asBytes();
306 const auto seg_sz = capnp_seg.size();
308 auto& blob = *blob_it;
310 assert((capnp_seg.begin() == &(blob.front()))
311 &&
"Somehow capnp-returned segments are out of order to allocateSegment() calls; or something....");
313 &&
"capnp shouldn't be generating zero-sized segments.");
314 assert((seg_sz <= blob.capacity())
315 &&
"capnp somehow overflowed the area we gave it.");
336 flow::util::Blob::S_UNCHANGED,
339 FLOW_LOG_TRACE(
"SHM builder [" << *
this <<
"]: "
340 "Serialization segment [" << idx <<
"] (0 based, of [" << capnp_segs.size() <<
"], 1-based): "
341 "SHM-arena buffer @[" <<
static_cast<const void*
>(&(blob.front())) <<
"] "
342 "sized [" << seg_sz <<
"]: Serialization of segment complete.");
343 FLOW_LOG_DATA(
"Segment contents: "
344 "[\n" << buffers_dump_string(
Blob_const(&(blob.front()), blob.size()),
" ") <<
"].");
352 const auto handle_serialization_blob = shm_session->template lend_object<Segments_in_shm>(m_serialization_segments);
354 if (handle_serialization_blob.empty())
360 FLOW_LOG_WARNING(
"SHM builder [" << *
this <<
"]: "
361 "After finalizing capnp-serialization in a SHM arena, SHM-session failed to register "
362 "attempt to lend a SHM-handle to this serialization to the opposing process. "
363 "The data structure cannot be transmitted to the opposing process. Assuming no bugs "
364 "up to this point, the session is down (usually means opposing process is down).");
370 auto capnp_segment_list_in_shm = capnp_root->hasSegmentListInShm() ? capnp_root->getSegmentListInShm()
371 : capnp_root->initSegmentListInShm();
383template<
typename Shm_arena>
384kj::ArrayPtr<::capnp::word>
387 using Word = ::capnp::word;
388 using Capnp_word_buf = kj::ArrayPtr<Word>;
389 using flow::util::ceil_div;
391 constexpr size_t WORD_SZ =
sizeof(Word);
405 = std::max(
size_t(min_sz),
408 size_t(ceil_div(m_segment_sz, WORD_SZ)))
411 FLOW_LOG_TRACE(
"SHM builder [" << *
this <<
"]: allocateSegment request for >=[" << min_sz <<
"] words; "
412 "SHM-allocing ~max(that x sizeof(word), next-size=[" << m_segment_sz <<
"]) = [" << seg_sz <<
"] "
420 buf_ptr = &(m_serialization_segments->emplace_back
423 get_logger()).front());
429 memset(buf_ptr, 0, seg_sz);
432 m_segment_sz += seg_sz;
436 FLOW_LOG_TRACE(
"SHM builder [" << *
this <<
"]: Next-size grew exponentially to [" << m_segment_sz <<
"] "
439 return Capnp_word_buf(
reinterpret_cast<Word*
>(buf_ptr),
440 reinterpret_cast<Word*
>(buf_ptr + seg_sz));
443template<
typename Shm_arena>
446 return os <<
'@' << &val;
RAII-style class operating a stack-like notion of a the given thread's currently active SHM-aware Are...
Stateless allocator usable with STL-compliant containers to store (or merely read) them directly in S...
A capnp::MessageBuilder used by shm::Builder: similar to a MallocMessageBuilder with the GROW_HEURIST...
Capnp_message_builder(flow::log::Logger *logger_ptr, Arena *arena)
Constructs the message-builder, memorizing the SHM engine it shall use to construct/allocate data int...
kj::ArrayPtr<::capnp::word > allocateSegment(unsigned int min_sz) override
Implements MessageBuilder API.
~Capnp_message_builder()
Decrements owner-process count by 1; if current count is 1 deallocates SHM-stored data.
flow::util::Basic_blob< Borrower_allocator< uint8_t > > Segment_in_shm_borrowed
For easier outside generic programming, this is the read-only-borrower counterpart to Segment_in_shm.
flow::util::Basic_blob< Allocator< uint8_t > > Segment_in_shm
The inner data structure stored in SHM representing one capnp-requested segment storing all or part o...
bipc::list< Segment_in_shm_borrowed, Borrower_allocator< Segment_in_shm_borrowed > > Segments_in_shm_borrowed
For easier outside generic programming, this is the read-only-borrower counterpart to Segments_in_shm...
size_t m_segment_sz
Minimum size of the next segment allocated by allocateSegment.
Arena::template Handle< Segments_in_shm > m_serialization_segments
Outer SHM handle to the data structured in SHM that stores the capnp-requested serialization segments...
bipc::list< Segment_in_shm, Allocator< Segment_in_shm > > Segments_in_shm
The outer data structured stored in SHM representing the entire list of capnp-requested segments Segm...
Shm_arena Arena
Short-hand for, you know.
bool lend(schema::detail::ShmTopSerialization::Builder *capnp_root, session::shm::Arena_to_shm_session_t< Arena > *shm_session)
To be called after being done mutating underlying structured data, increments owner-process count by ...
Small group of miscellaneous utilities to ease work with capnp (Cap'n Proto), joining its capnp names...
typename Arena_to_shm_session< Arena >::Type Arena_to_shm_session_t
Alias that, given an Arena type (with Arena::construct<T>() which allocates/constructs a T),...
Builder< ipc::shm::classic::Pool_arena > Builder
Convenience alias: transport::struc::shm::Builder that works with boost.ipc.shm pools from ipc::shm::...
Segregates zero-copy/SHM implementations of concepts residing in parent namespace ipc::transport::str...
void capnp_set_lent_shm_handle(schema::ShmHandle::Builder *shm_handle_root, const flow::util::Blob_sans_log_context &lend_result)
Utility that saves the result of a Shm_session1::lend_object<T>(const shared_ptr<T>&) result into the...
std::ostream & operator<<(std::ostream &os, const Capnp_message_builder< Shm_arena > &val)
Prints string representation of the given Capnp_message_builder to the given ostream.
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.
Log_component
The flow::log::Component payload enumeration containing various log components used by Flow-IPC inter...