24#include <boost/noncopyable.hpp>
76#ifdef IPC_DOXYGEN_ONLY
78template<
typename Msg_resource_t,
bool NO_HNDLS = true>
83template<typename Msg_resource_t, bool NO_HNDLS>
87 :
private boost::noncopyable
113#ifdef IPC_DOXYGEN_ONLY
281template<
typename Msg_resource_t,
bool NO_HNDLS>
284 m_resource(std::move(msg_resource)),
291template<
typename Msg_resource_t,
bool NO_HNDLS>
295 m_batch.reserve(max_msg_count);
297 assert((
m_batch.capacity() == max_msg_count) &&
"We use .capacity() to memorize `max_msg_count` for full(), etc.");
300template<
typename Msg_resource_t,
bool NO_HNDLS>
304 if (target_payload_size() != 0)
306 assert((target_payload_size() == target_blob.size())
307 &&
"Msg_batch_in concept requires the max message size be the same across all slots.");
310 if (idx ==
size_t(-1))
313 assert((!initialized())
314 &&
"At this time the fully-initialized batch size shall be permanently set via ctor; cannot grow.");
316 m_batch.emplace_back(target_blob, std::move(msg_resource));
318 else if (idx < m_batch.size())
320 auto& mdt = m_batch[idx];
321 mdt.m_buf_seq = target_blob;
322 mdt.m_resource = std::move(msg_resource);
326 assert(
false &&
"prepare_target_payload(x) must either replace an existing slot x or add slot via `x = -1`.");
330template<
typename Msg_resource_t,
bool NO_HNDLS>
333 return m_batch.empty() ? 0
334 : m_batch.front().m_buf_seq.size();
337template<
typename Msg_resource_t,
bool NO_HNDLS>
341 assert(idx < m_batch.size());
344 auto& mdt = m_batch[idx];
345 if (msg_resource_ptr)
347 *msg_resource_ptr = &mdt.m_resource;
350 return mdt.m_result_n_rcvd;
353template<
typename Msg_resource_t,
bool NO_HNDLS>
356 static_assert(!S_NO_HNDLS,
"Do not invoke/instantiate this method if class tparam NO_HNDLS=true.");
358 assert(idx < m_batch.size());
361 return m_batch[idx].m_result_hndl_unless_no_hndls;
364template<
typename Msg_resource_t,
bool NO_HNDLS>
367 static_assert(!S_NO_HNDLS,
"Do not invoke/instantiate this method if class tparam NO_HNDLS=true.");
370 return &(m_batch[m_n_used].m_result_hndl_unless_no_hndls);
373template<
typename Msg_resource_t,
bool NO_HNDLS>
377 return m_batch[m_n_used].m_buf_seq;
380template<
typename Msg_resource_t,
bool NO_HNDLS>
383 return m_batch.size() == m_batch.capacity();
386template<
typename Msg_resource_t,
bool NO_HNDLS>
392template<
typename Msg_resource_t,
bool NO_HNDLS>
395 return m_n_used == m_batch.size();
398template<
typename Msg_resource_t,
bool NO_HNDLS>
404template<
typename Msg_resource_t,
bool NO_HNDLS>
407 m_n_used = new_n_used;
410template<
typename Msg_resource_t,
bool NO_HNDLS>
413 assert(initialized() &&
"By contract must prepare_target_payload() to create all max_msg_count slots. "
414 "Can check initialized() to ensure that is the case before calling us.");
417 m_batch[m_n_used].m_result_n_rcvd = result_n_rcvd;
421template<
typename Msg_resource_t,
bool NO_HNDLS>
425 os <<
"Gen[slots-total/rdy/rcvd [" << m_batch.size() <<
'/' << m_batch.capacity() <<
'/' << m_n_used <<
"] "
426 "blob-sz[" << target_payload_size() <<
"]]@" <<
this;
430template<
typename Msg_resource_t,
bool NO_HNDLS>
Straightforward Msg_batch_in concept implementation (as taken by API {Blob|Native_handle}_receiver::a...
Msg_resource_t Msg_resource
See Msg_batch_in concept API.
~Generic_msg_batch_in()
See Msg_batch_in concept API.
bool full() const
See Msg_batch_in concept API.
util::Blob_mutable Mutable_buffer_sequence
See Msg_batch_in concept API.
std::vector< Mdt_per_payload > m_batch
The slots. .capacity() == max_msg_count (see ctor); .size() is same once initialized().
Native_handle * next_target_hndl()
For use by receiver-engine (not receiver-user), returns pointer to the target Native_handle for slot ...
size_t m_n_used
See n_used().
size_t target_payload_size() const
See Msg_batch_in concept API.
void prepare_target_payload(const Mutable_buffer_sequence &target_blob, Msg_resource &&msg_resource, size_t idx=-1)
See Msg_batch_in concept API.
static constexpr bool S_NO_HNDLS
See Msg_batch_in concept API.
void clear_used()
See Msg_batch_in concept API.
util::Blob_mutable next_target_blob()
For use by receiver-engine (not receiver-user), returns the location/size of the target memory area f...
Generic_msg_batch_in(size_t max_msg_count)
See Msg_batch_in concept API.
size_t n_used() const
See Msg_batch_in concept API.
size_t result_payload_blob(size_t idx, Msg_resource **msg_resource_ptr=nullptr)
See Msg_batch_in concept API; plus additional behavior for arg idx (allowed to be >= n_used()).
void to_ostream(std::ostream *os) const
Prints string representation to the given ostream.
void emulate_result(size_t result_n_rcvd)
For use by receiver-engine (not receiver-user), records the size of the successful receive at slot wi...
bool initialized() const
See Msg_batch_in concept API.
Native_handle result_payload_hndl(size_t idx) const
See Msg_batch_in concept API; plus additional behavior for arg idx (allowed to be >= n_used()).
Flow-IPC module providing transmission of structured messages and/or low-level blobs (and more) betwe...
std::ostream & operator<<(std::ostream &os, const Generic_msg_batch_in< Msg_resource_t, NO_HNDLS > &val)
Prints string representation of the given Generic_msg_batch_in to the given ostream.
boost::asio::mutable_buffer Blob_mutable
Short-hand for a mutable blob somewhere in memory, stored as exactly a void* and a size_t.
Msg_resource m_resource
Per-slot resource moved from user's object via prepare_target_payload().
Native_handle m_result_hndl_unless_no_hndls
The target/result Native_handle to receive-to for this slot; null originally; null or not upon a rece...
Mutable_buffer_sequence m_buf_seq
The target memory location for where to receive-to for this slot.
Mdt_per_payload(const Mutable_buffer_sequence &buf_seq, Msg_resource &&msg_resource)
Ctor.
size_t m_result_n_rcvd
The target/result containing the # of bytes successfully read into area m_buf_seq for this slot.
A monolayer-thin wrapper around a native handle, a/k/a descriptor a/k/a FD.