23#include <boost/interprocess/smart_ptr/shared_ptr.hpp>
24#include <boost/move/make_unique.hpp>
25#include <boost/compressed_pair.hpp>
274template<
typename Allocator,
bool SHARING>
297 static_assert(std::is_same_v<typename Allocator_raw::value_type, value_type>,
298 "Allocator template param must be of form A<V> where V is our value_type.");
359 static constexpr bool S_IS_VANILLA_ALLOC = std::is_same_v<Allocator_raw, std::allocator<value_type>>;
704 template<typename Emit_blob_func>
706 log::Logger* logger_ptr =
nullptr);
723 template<typename Blob_container>
725 log::Logger* logger_ptr =
nullptr);
744 template<typename Blob_ptr_container>
746 log::Logger* logger_ptr =
nullptr);
808 log::Logger* logger_ptr =
nullptr) const;
1245 template<typename Emit_blob_func, typename Share_after_split_left_func>
1247 Emit_blob_func&& emit_blob_func,
1248 log::Logger* logger_ptr,
1249 Share_after_split_left_func&& share_after_split_left_func);
1302 using Pointer_raw =
typename std::allocator_traits<Allocator_raw>::pointer;
1338 Deleter_raw(Deleter_raw&& moved_src);
1497 boost::shared_ptr<value_type[]>,
1498 boost::movelib::unique_ptr<value_type[]>>,
1500 boost::interprocess::shared_ptr
1502 boost::movelib::unique_ptr<value_type, Deleter_raw>>>;
1669template<
typename Allocator,
bool SHARING>
1671 m_alloc_and_buf_ptr(alloc_raw_src),
1679template<
typename Allocator,
bool SHARING>
1688template<
typename Allocator,
bool SHARING>
1697template<
typename Allocator,
bool SHARING>
1710template<
typename Allocator,
bool SHARING>
1713 m_alloc_and_buf_ptr(std::move(moved_src.alloc_raw())),
1720 swap_impl(moved_src, logger_ptr);
1723template<
typename Allocator,
bool SHARING>
1726template<
typename Allocator,
bool SHARING>
1733 if constexpr(S_SHARING)
1739 if constexpr(std::allocator_traits<Allocator_raw>::propagate_on_container_copy_assignment::value)
1789template<
typename Allocator,
bool SHARING>
1795template<
typename Allocator,
bool SHARING>
1799 if (
this != &moved_src)
1802 if constexpr(std::allocator_traits<Allocator_raw>::propagate_on_container_move_assignment::value)
1804 alloc_raw() = std::move(moved_src.alloc_raw());
1815 make_zero(logger_ptr);
1818 swap_impl(moved_src, logger_ptr);
1826template<
typename Allocator,
bool SHARING>
1830 return assign(std::move(moved_src));
1833template<
typename Allocator,
bool SHARING>
1847 "swapping <=> Blob [" << &other <<
"] (internal buffer sized "
1848 "[" << other.capacity() <<
"]).");
1863 swap(buf_ptr(), other.buf_ptr());
1869#pragma GCC diagnostic push
1870#pragma GCC diagnostic ignored "-Wpragmas"
1871#pragma GCC diagnostic ignored "-Wunknown-warning-option"
1872#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
1874 swap(m_capacity, other.m_capacity);
1875 swap(m_size, other.m_size);
1876 swap(m_start, other.m_start);
1878#pragma GCC diagnostic pop
1885template<
typename Allocator,
bool SHARING>
1891 if constexpr(std::allocator_traits<Allocator_raw>::propagate_on_container_swap::value)
1893 if (&alloc_raw() != &other.alloc_raw())
1895 swap(alloc_raw(), other.alloc_raw());
1906 swap_impl(other, logger_ptr);
1909template<
typename Allocator,
bool SHARING>
1913 return blob1.swap(blob2, logger_ptr);
1916template<
typename Allocator,
bool SHARING>
1919 static_assert(S_SHARING,
1920 "Do not invoke (and thus instantiate) share() or derived methods unless you set the SHARING "
1921 "template parameter to true. Sharing will be enabled at a small perf cost; see class doc header.");
1926 Basic_blob sharing_blob{alloc_raw(), logger_ptr};
1927 assert(!sharing_blob.buf_ptr());
1928 sharing_blob.buf_ptr() = buf_ptr();
1930 sharing_blob.m_capacity = m_capacity;
1931 sharing_blob.m_start = m_start;
1932 sharing_blob.m_size = m_size;
1938 (
"Blob [" <<
this <<
"] shared with new Blob [" << &sharing_blob <<
"]; ref-count incremented.");
1941 return sharing_blob;
1944template<
typename Allocator,
bool SHARING>
1948 if (lt_size > size())
1957 "[" << lt_size <<
"] values into that one and leaving the remaining "
1958 "[" << (size() - lt_size) <<
"] in this one.");
1961 auto sharing_blob = share(logger_ptr);
1962 sharing_blob.resize(lt_size);
1963 start_past_prefix_inc(lt_size);
1965 return sharing_blob;
1968template<
typename Allocator,
bool SHARING>
1972 if (rt_size > size())
1977 const auto lt_size = size() - rt_size;
1982 "the last [" << rt_size <<
"] values into that one and leaving the "
1983 "remaining [" << lt_size <<
"] in this one.");
1986 auto sharing_blob = share(logger_ptr);
1988 sharing_blob.start_past_prefix_inc(lt_size);
1990 return sharing_blob;
1993template<
typename Allocator,
bool SHARING>
1994template<
typename Emit_blob_func,
typename Share_after_split_left_func>
1997 Share_after_split_left_func&& share_after_split_left_func)
2006 "adjacent sharing sub-Blobs of size [" << size <<
"] each "
2007 "(last one possibly smaller).");
2012 emit_blob_func(share_after_split_left_func(size, logger_ptr));
2018 make_zero(logger_ptr);
2022template<
typename Allocator,
bool SHARING>
2023template<
typename Emit_blob_func>
2025 Emit_blob_func&& emit_blob_func,
2028 share_after_split_equally_impl(size, headless_pool, std::move(emit_blob_func), logger_ptr,
2031 return share_after_split_left(lt_size, logger_ptr);
2035template<
typename Allocator,
bool SHARING>
2036template<
typename Blob_container>
2042 assert(out_blobs_ptr);
2043 share_after_split_equally(size, headless_pool, [&](
Basic_blob&& blob_moved)
2045 out_blobs_ptr->push_back(std::move(blob_moved));
2049template<
typename Allocator,
bool SHARING>
2050template<
typename Blob_ptr_container>
2053 Blob_ptr_container* out_blobs_ptr,
2059 using Ptr =
typename Blob_ptr_container::value_type;
2061 assert(out_blobs_ptr);
2063 share_after_split_equally(size, headless_pool, [&](
Basic_blob&& blob_moved)
2065 out_blobs_ptr->push_back(Ptr{
new Basic_blob{std::move(blob_moved)}});
2069template<
typename Allocator,
bool SHARING>
2073 static_assert(SHARING,
2074 "blobs_sharing() would only make sense on `Basic_blob`s with SHARING=true. "
2075 "Even if we were to allow this to instantiate (compile) it would always return false.");
2077 return ((!blob1.
zero()) && (!blob2.
zero()))
2078 && ((&blob1 == &blob2)
2085template<
typename Allocator,
bool SHARING>
2088 return zero() ? 0 : m_size;
2091template<
typename Allocator,
bool SHARING>
2094 return zero() ? 0 : m_start;
2097template<
typename Allocator,
bool SHARING>
2103template<
typename Allocator,
bool SHARING>
2106 return zero() ? 0 : m_capacity;
2109template<
typename Allocator,
bool SHARING>
2115template<
typename Allocator,
bool SHARING>
2118 reserve_impl(new_capacity,
false, logger_ptr);
2121template<
typename Allocator,
bool SHARING>
2124 reserve_impl(new_capacity,
true, logger_ptr);
2127template<
typename Allocator,
bool SHARING>
2130 using boost::make_shared_noinit;
2131 using boost::make_shared;
2132 using boost::shared_ptr;
2133 using std::numeric_limits;
2138 assert((zero() || ((new_capacity <= m_capacity) && (m_capacity > 0)))
2139 &&
"Basic_blob intentionally disallows reserving N>M>0, where M is current capacity. make_zero() first.");
2145 if (zero() && (new_capacity != 0))
2151 "allocating internal buffer sized [" << new_capacity <<
"]; "
2152 "will zero-fill? = [" << clear_on_alloc <<
"].");
2155 if (new_capacity <=
size_type(numeric_limits<difference_type>::max()))
2162 if constexpr(S_IS_VANILLA_ALLOC)
2175 if constexpr(S_SHARING)
2181 buf_ptr().reset(clear_on_alloc ? (
new value_type[new_capacity]()) : (
new value_type[new_capacity]),
2183 [logger_ptr, original_blob =
this, new_capacity]
2187 FLOW_LOG_TRACE(
"Deallocating internal buffer sized [" << new_capacity <<
"] originally allocated by "
2188 "Blob [" << original_blob <<
"]; note that Blob may now be gone and furthermore another "
2189 "Blob might live at that address now. A message immediately preceding this one should "
2190 "indicate the last Blob to give up ownership of the internal buffer.");
2192 delete [] buf_ptr_to_delete;
2199 buf_ptr() = clear_on_alloc ? make_shared<value_type[]>(new_capacity)
2200 : make_shared_noinit<value_type[]>(new_capacity);
2205 buf_ptr() = clear_on_alloc ? boost::movelib::make_unique<value_type[]>(new_capacity)
2206 : boost::movelib::make_unique_definit<value_type[]>(new_capacity);
2216 const auto ptr = alloc_raw().allocate(new_capacity);
2218 if constexpr(S_SHARING)
2220 buf_ptr().reset(ptr,
2269 buf_ptr().get_deleter() =
Deleter_raw{alloc_raw(), new_capacity};
2270 buf_ptr().reset(ptr);
2275 memset(ptr.get(), 0, new_capacity);
2320 assert(
false &&
"Enormous or corrupt new_capacity?!");
2347 m_capacity = new_capacity;
2357 assert(capacity() >= new_capacity);
2360template<
typename Allocator,
bool SHARING>
2364 resize_impl(new_size,
false, new_start_or_unchanged, logger_ptr);
2367template<
typename Allocator,
bool SHARING>
2371 resize_impl(new_size,
true, new_start_or_unchanged, logger_ptr);
2374template<
typename Allocator,
bool SHARING>
2378 auto& new_start = new_start_or_unchanged;
2379 if (new_start == S_UNCHANGED)
2381 new_start = start();
2384 const size_type min_capacity = new_start + new_size;
2391 reserve_impl(min_capacity, clear_on_alloc, logger_ptr);
2392 assert(capacity() >= min_capacity);
2397 m_start = new_start;
2401 assert(size() == new_size);
2402 assert(start() == new_start);
2405template<
typename Allocator,
bool SHARING>
2408 resize(((start() + size()) > prefix_size)
2409 ? (start() + size() - prefix_size)
2415template<
typename Allocator,
bool SHARING>
2418 assert((prefix_size_inc >= 0) || (start() >=
size_type(-prefix_size_inc)));
2419 start_past_prefix(start() + prefix_size_inc);
2422template<
typename Allocator,
bool SHARING>
2430template<
typename Allocator,
bool SHARING>
2440 if constexpr(SHARING)
2443 "[" << capacity() <<
"]; deallocation will immediately follow if no sharing "
2444 "`Blob`s remain; else ref-count merely decremented.");
2449 "[" << capacity() <<
"].");
2457template<
typename Allocator,
bool SHARING>
2466 resize(n, 0, logger_ptr);
2469 emplace_copy(const_begin(), src, logger_ptr);
2476template<
typename Allocator,
bool SHARING>
2485 assert(valid_iterator(dest));
2487 const Iterator dest_it = iterator_sans_const(dest);
2498 "memory area [" <<
static_cast<const void*
>(src_data) <<
"] sized "
2499 "[" << n <<
"] to internal buffer at offset [" << (dest - const_begin()) <<
"].");
2502 assert(derefable_iterator(dest_it));
2506 assert(((dest_it + n) <= src_data) || ((src_data + n) <= dest_it));
2520#pragma GCC diagnostic push
2521#pragma GCC diagnostic ignored "-Wpragmas"
2522#pragma GCC diagnostic ignored "-Wunknown-warning-option"
2523#pragma GCC diagnostic ignored "-Wstringop-overflow"
2524#pragma GCC diagnostic ignored "-Wrestrict"
2530 memcpy(dest_it, src_data, n);
2532#pragma GCC diagnostic pop
2538template<
typename Allocator,
bool SHARING>
2547 assert(valid_iterator(src));
2552 const auto dest_data =
static_cast<Iterator>(dest.data());
2558 "memory area [" <<
static_cast<const void*
>(dest_data) <<
"] sized "
2559 "[" << n <<
"] from internal buffer offset [" << (src - const_begin()) <<
"].");
2562 assert(derefable_iterator(src));
2565 assert(((src + n) <= dest_data) || ((dest_data + n) <= src));
2568#pragma GCC diagnostic push
2569#pragma GCC diagnostic ignored "-Wpragmas"
2570#pragma GCC diagnostic ignored "-Wunknown-warning-option"
2571#pragma GCC diagnostic ignored "-Wstringop-overflow"
2572#pragma GCC diagnostic ignored "-Wrestrict"
2573 memcpy(dest_data, src, n);
2574#pragma GCC diagnostic pop
2580template<
typename Allocator,
bool SHARING>
2586 assert(derefable_iterator(first));
2587 assert(valid_iterator(past_last));
2589 const Iterator dest = iterator_sans_const(first);
2591 if (past_last > first)
2593 const auto n_moved =
size_type(const_end() - past_last);
2598#pragma GCC diagnostic push
2599#pragma GCC diagnostic ignored "-Wpragmas"
2600#pragma GCC diagnostic ignored "-Wunknown-warning-option"
2601#pragma GCC diagnostic ignored "-Wstringop-overflow"
2602#pragma GCC diagnostic ignored "-Wrestrict"
2603 memmove(dest, iterator_sans_const(past_last), n_moved);
2604#pragma GCC diagnostic pop
2608 m_size -= (past_last - first);
2616template<
typename Allocator,
bool SHARING>
2621 return *const_begin();
2624template<
typename Allocator,
bool SHARING>
2629 return const_end()[-1];
2632template<
typename Allocator,
bool SHARING>
2640template<
typename Allocator,
bool SHARING>
2648template<
typename Allocator,
bool SHARING>
2652 return const_front();
2655template<
typename Allocator,
bool SHARING>
2659 return const_back();
2662template<
typename Allocator,
bool SHARING>
2666 return const_cast<Basic_blob*
>(
this)->begin();
2669template<
typename Allocator,
bool SHARING>
2689 const auto raw_or_fancy_buf_ptr = buf_ptr().get();
2690 return &(*raw_or_fancy_buf_ptr) + m_start;
2693template<
typename Allocator,
bool SHARING>
2697 return zero() ? const_begin() : (const_begin() + size());
2700template<
typename Allocator,
bool SHARING>
2704 return zero() ? begin() : (begin() + size());
2707template<
typename Allocator,
bool SHARING>
2711 return const_begin();
2714template<
typename Allocator,
bool SHARING>
2718 return const_begin();
2721template<
typename Allocator,
bool SHARING>
2728template<
typename Allocator,
bool SHARING>
2735template<
typename Allocator,
bool SHARING>
2739 return const_begin();
2742template<
typename Allocator,
bool SHARING>
2749template<
typename Allocator,
bool SHARING>
2752 return empty() ? (it == const_end())
2756template<
typename Allocator,
bool SHARING>
2759 return empty() ? false
2763template<
typename Allocator,
bool SHARING>
2770template<
typename Allocator,
bool SHARING>
2773 return boost::asio::const_buffer{const_data(), size()};
2776template<
typename Allocator,
bool SHARING>
2779 return boost::asio::mutable_buffer{data(), size()};
2782template<
typename Allocator,
bool SHARING>
2789template<
typename Allocator,
bool SHARING>
2792 return m_alloc_and_buf_ptr.second();
2795template<
typename Allocator,
bool SHARING>
2799 return const_cast<Basic_blob*
>(
this)->buf_ptr();
2802template<
typename Allocator,
bool SHARING>
2805 return m_alloc_and_buf_ptr.first();
2808template<
typename Allocator,
bool SHARING>
2812 return const_cast<Basic_blob*
>(
this)->alloc_raw();
2816template<
typename Allocator,
bool SHARING>
2824template<
typename Allocator,
bool SHARING>
2828 m_alloc_raw(std::in_place, alloc_raw_src),
2834template<
typename Allocator,
bool SHARING>
2845template<
typename Allocator,
bool SHARING>
2848template<
typename Allocator,
bool SHARING>
2854 if (
this != &moved_src)
2857 swap(m_buf_sz, moved_src.m_buf_sz);
2868 if (!moved_src.m_alloc_raw)
2871 m_alloc_raw.reset();
2876 const auto& src_alloc_raw = *moved_src.m_alloc_raw;
2877 if ((!m_alloc_raw) || (*m_alloc_raw != src_alloc_raw))
2879 m_alloc_raw.emplace(src_alloc_raw);
2884 moved_src.m_alloc_raw.reset();
2891template<
typename Allocator,
bool SHARING>
2905 m_alloc_raw.reset();
2910 if ((!m_alloc_raw) || (*m_alloc_raw != src_alloc_raw))
2912 m_alloc_raw.emplace(src_alloc_raw);
2920template<
typename Allocator,
bool SHARING>
2926 m_alloc_raw->deallocate(to_delete, m_buf_sz);
Interface that the user should implement, passing the implementing Logger into logging classes (Flow'...
virtual bool should_log(Sev sev, const Component &component) const =0
Given attributes of a hypothetical message that would be logged, return true if that message should b...
Internal deleter functor used if and only if S_IS_VANILLA_ALLOC is false and therefore only with Buf_...
Pointer_raw pointer
For boost::interprocess::shared_ptr and unique_ptr compliance (hence the irregular capitalization).
typename std::allocator_traits< Allocator_raw >::pointer Pointer_raw
Short-hand for the allocator's pointer type, pointing to Basic_blob::value_type.
std::optional< Allocator_raw > m_alloc_raw
See ctor: the allocator that operator()() shall use to deallocate.
size_type m_buf_sz
See ctor and operator()(): the size of the buffer to deallocate.
Deleter_raw()
Default ctor: Deleter must never be invoked to delete anything in this state; suitable only for a nul...
void operator()(Pointer_raw to_delete)
Deallocates using Allocator_raw::deallocate(), passing-in the supplied pointer (to value_type) to_del...
Deleter_raw(const Deleter_raw &src)
Copy-construction which may be required when we are used in boost::interprocess::shared_ptr which as ...
Deleter_raw & operator=(Deleter_raw &&moved_src)
Move-assignment which is required when we are used in unique_ptr.
A hand-optimized and API-tweaked replacement for vector<uint8_t>, i.e., buffer of bytes inside an all...
Basic_blob(Basic_blob &&moved_src, log::Logger *logger_ptr=nullptr) noexcept
Move constructor, constructing a blob exactly internally equal to pre-call moved_src,...
value_type const * const_data() const
Equivalent to const_begin().
Allocator Allocator_raw
Short-hand for the allocator type specified at compile-time. Its element type is our value_type.
bool valid_iterator(Const_iterator it) const
Returns true if and only if: this->derefable_iterator(it) || (it == this->const_end()).
value_type const * Const_iterator
Type for iterator pointing into an immutable structure of this type.
Basic_blob(const Allocator_raw &alloc_raw_src={})
Constructs blob with zero() == true.
size_type m_start
See start(); but m_start is meaningless (and containing unknown value) if !buf_ptr() (i....
Const_iterator const_begin() const
Returns pointer to immutable first element; or end() if empty().
Basic_blob share_after_split_left(size_type size, log::Logger *logger_ptr=nullptr)
Applicable to !zero() blobs, this shifts this->begin() by size to the right without changing end(); a...
value_type * Iterator
Type for iterator pointing into a mutable structure of this type.
bool zero() const
Returns false if a buffer is allocated and owned; true otherwise.
void start_past_prefix(size_type prefix_size)
Restructures blob to consist of an internally allocated buffer and a [begin(), end) range starting at...
bool empty() const
Returns size() == 0.
Basic_blob share_after_split_right(size_type size, log::Logger *logger_ptr=nullptr)
Identical to share_after_split_left(), except this->end() shifts by size to the left (instead of this...
Iterator iterator_sans_const(Const_iterator it)
Returns iterator-to-mutable equivalent to given iterator-to-immutable.
Iterator emplace_copy(Const_iterator dest, const boost::asio::const_buffer &src, log::Logger *logger_ptr=nullptr)
Copies src buffer directly onto equally sized area within *this at location dest; *this must have suf...
const value_type & back() const
Equivalent to const_back().
size_type capacity() const
Returns the number of elements in the internally allocated buffer, which is 1 or more; or 0 if no buf...
const value_type & const_reference
For container compliance (hence the irregular capitalization): reference to const element.
static constexpr Flow_log_component S_LOG_COMPONENT
Our flow::log::Component.
void swap(Basic_blob &other, log::Logger *logger_ptr=nullptr) noexcept
Swaps the contents of this structure and other, or no-op if this == &other.
size_type m_size
See size(); but m_size is meaningless (and containing unknown value) if !buf_ptr() (i....
std::size_t size_type
Type for index into blob or length of blob or sub-blob.
Const_iterator const_end() const
Returns pointer one past immutable last element; empty() is possible.
Iterator erase(Const_iterator first, Const_iterator past_last)
Performs the minimal number of operations to make range [begin(), end()) unchanged except for lacking...
const Buf_ptr & buf_ptr() const
Ref-to-immutable counterpart to the other overload.
void share_after_split_equally_impl(size_type size, bool headless_pool, Emit_blob_func &&emit_blob_func, log::Logger *logger_ptr, Share_after_split_left_func &&share_after_split_left_func)
Impl of share_after_split_equally() but capable of emitting not just *this type (Basic_blob<....
Iterator pointer
For container compliance (hence the irregular capitalization): pointer to element.
std::conditional_t< S_IS_VANILLA_ALLOC, std::conditional_t< S_SHARING, boost::shared_ptr< value_type[]>, boost::movelib::unique_ptr< value_type[]> >, std::conditional_t< S_SHARING, boost::interprocess::shared_ptr< value_type, Allocator_raw, Deleter_raw >, boost::movelib::unique_ptr< value_type, Deleter_raw > > > Buf_ptr
The smart-pointer type used for buf_ptr(); a custom-allocator-and-SHM-friendly impl and parameterizat...
Basic_blob share(log::Logger *logger_ptr=nullptr) const
Applicable to !zero() blobs, this returns an identical Basic_blob that shares (co-owns) *this allocat...
Iterator iterator
For container compliance (hence the irregular capitalization): Iterator type.
void reserve_impl(size_type capacity, bool clear_on_alloc, log::Logger *logger_ptr)
Implements reserve() overloads.
boost::compressed_pair< Allocator_raw, Buf_ptr > m_alloc_and_buf_ptr
Combined – to enable empty base-class optimization (EBO) – storage for the two data items,...
value_type & reference
For container compliance (hence the irregular capitalization): reference to element.
void make_zero(log::Logger *logger_ptr=nullptr)
Guarantees post-condition zero() == true by dropping *this ownership of the allocated internal buffer...
void reserve(size_type capacity, log::Logger *logger_ptr=nullptr)
Ensures that an internal buffer of at least capacity elements is allocated and owned; disallows growi...
void resize_impl(size_type size, bool clear_on_alloc, size_type start_or_unchanged, log::Logger *logger_ptr)
Implements resize() overloads.
size_type assign_copy(const boost::asio::const_buffer &src, log::Logger *logger_ptr=nullptr)
Replaces logical contents with a copy of the given non-overlapping area anywhere in memory.
void clear()
Equivalent to resize(0, start()).
boost::asio::const_buffer const_buffer() const
Convenience accessor returning an immutable boost.asio buffer "view" into the entirety of the blob.
Basic_blob & assign(Basic_blob &&moved_src, log::Logger *logger_ptr=nullptr) noexcept
Move assignment.
value_type * data()
Equivalent to begin().
static constexpr bool S_IS_VANILLA_ALLOC
true if Allocator_raw underlying allocator template is simply std::allocator; false otherwise.
Const_iterator cend() const
Synonym of const_end().
void share_after_split_equally_emit_seq(size_type size, bool headless_pool, Blob_container *out_blobs, log::Logger *logger_ptr=nullptr)
share_after_split_equally() wrapper that places Basic_blobs into the given container via push_back().
const value_type & front() const
Equivalent to const_front().
static constexpr size_type S_UNCHANGED
Special value indicating an unchanged size_type value; such as in resize().
void resize(size_type size, size_type start_or_unchanged=S_UNCHANGED, log::Logger *logger_ptr=nullptr)
Guarantees post-condition size() == size and start() == start; no values in pre-call range [begin(),...
const Allocator_raw & alloc_raw() const
Ref-to-immutable counterpart to the other overload.
uint8_t value_type
Short-hand for values, which in this case are unsigned bytes.
Basic_blob(size_type size, Clear_on_alloc coa_tag, log::Logger *logger_ptr=nullptr, const Allocator_raw &alloc_raw_src={})
Identical to similar-sig ctor except, if size > 0, all size elements are performantly initialized to ...
Const_iterator cbegin() const
Synonym of const_begin().
Iterator begin()
Returns pointer to mutable first element; or end() if empty().
Const_iterator const_pointer
For container compliance (hence the irregular capitalization): pointer to const element.
void share_after_split_equally(size_type size, bool headless_pool, Emit_blob_func &&emit_blob_func, log::Logger *logger_ptr=nullptr)
Identical to successively performing share_after_split_left(size) until this->empty() == true; the re...
std::ptrdiff_t difference_type
Type for difference of size_types.
Const_iterator const_iterator
For container compliance (hence the irregular capitalization): Const_iterator type.
static constexpr bool S_SHARING
Value of template parameter SHARING (for generic programming).
Basic_blob & operator=(Basic_blob &&moved_src) noexcept
Move assignment operator (no logging): equivalent to assign(std::move(moved_src), nullptr).
size_type m_capacity
See capacity(); but m_capacity is meaningless (and containing unknown value) if !buf_ptr() (i....
~Basic_blob()
Destructor that drops *this ownership of the allocated internal buffer if any, as by make_zero(); if ...
void share_after_split_equally_emit_ptr_seq(size_type size, bool headless_pool, Blob_ptr_container *out_blobs, log::Logger *logger_ptr=nullptr)
share_after_split_equally() wrapper that places Ptr<Basic_blob>s into the given container via push_ba...
const value_type & const_back() const
Returns reference to immutable last element.
size_type start() const
Returns the offset between begin() and the start of the internally allocated buffer.
bool derefable_iterator(Const_iterator it) const
Returns true if and only if the given iterator points to an element within this blob's size() element...
Allocator_raw get_allocator() const
Returns a copy of the internally cached Allocator_raw as set by a constructor or assign() or assignme...
Buf_ptr & buf_ptr()
For convenience/expressiveness, the pointer-to-main-buf for *this.
void start_past_prefix_inc(difference_type prefix_size_inc)
Like start_past_prefix() but shifts the current prefix position by the given incremental value (posit...
void swap_impl(Basic_blob &other, log::Logger *logger_ptr) noexcept
The body of swap(), except for the part that swaps (or decides not to swap) alloc_raw().
Iterator end()
Returns pointer one past mutable last element; empty() is possible.
const value_type & const_front() const
Returns reference to immutable first element.
Allocator_raw & alloc_raw()
For convenience/expressiveness, the allocator object for *this.
boost::asio::mutable_buffer mutable_buffer()
Same as const_buffer() but the returned view is mutable.
size_type size() const
Returns number of elements stored, namely end() - begin().
Const_iterator sub_copy(Const_iterator src, const boost::asio::mutable_buffer &dest, log::Logger *logger_ptr=nullptr) const
The opposite of emplace_copy() in every way, copying a sub-blob onto a target memory area.
Basic_blob(size_type size, log::Logger *logger_ptr=nullptr, const Allocator_raw &alloc_raw_src={})
Constructs blob with size() and capacity() equal to the given size, and start() == 0.
#define FLOW_LOG_TRACE_WITHOUT_CHECKING(ARG_stream_fragment)
Logs a TRACE message into flow::log::Logger *get_logger() with flow::log::Component get_log_component...
#define FLOW_LOG_SET_CONTEXT(ARG_logger_ptr, ARG_component_payload)
For the rest of the block within which this macro is instantiated, causes all FLOW_LOG_....
#define FLOW_LOG_TRACE(ARG_stream_fragment)
Logs a TRACE message into flow::log::Logger *get_logger() with flow::log::Component get_log_component...
@ S_TRACE
Message indicates any condition that may occur with great frequency (thus verbose if logged).
Flow module containing miscellaneous general-use facilities that don't fit into any other Flow module...
bool in_closed_open_range(T const &min_val, T const &val, T const &max_val)
Returns true if and only if the given value is within the given range, given as a [low,...
bool blobs_sharing(const Basic_blob< Allocator, SHARING > &blob1, const Basic_blob< Allocator, SHARING > &blob2)
Returns true if and only if both given objects are not zero() == true, and they either co-own a commo...
void swap(Basic_blob< Allocator, SHARING > &blob1, Basic_blob< Allocator, SHARING > &blob2, log::Logger *logger_ptr) noexcept
Equivalent to blob1.swap(blob2).
bool in_closed_range(T const &min_val, T const &val, T const &max_val)
Returns true if and only if the given value is within the given range, inclusive.
Flow_log_component
The flow::log::Component payload enumeration comprising various log components used by Flow's own int...
unsigned char uint8_t
Byte. Best way to represent a byte of binary data. This is 8 bits on all modern systems.
Tag type used at least in Basic_blob and Blob_with_log_context to specify that an allocated buffer be...