Repository navigation
- flow.util:
- Add
flow::util::statsub-namespace: Facilities for working with simple stat-holdingstructs ("stat-sets"). Each data member ("stat-member") is classified as an accumulator (counter), gauge, or high-water mark of a particular gauge. Flow-IPC/ipc#164- Add
Histogram_counter: Usable as accumulator stat-member and standalone. - Stat-consuming API: Direct-read stat-members from stat-sets; reset and pretty-print stat-sets; more.
- Stat-collecting API: Collect under concurrency (optionally with thread-local sharding) or single-threaded; or integrate with third-party stat sources.
- Add
- Add thread-local-related utilities:
flow::util::Thread_local_state_registry<T>: A thread-localTper thread, plus access to all extant threads'Ts. CompanionsPoll_flagandPolled_shared_state<Shared_state>support signaling a rare cross-thread request that each thread notices cheaply on its fast-path. #119Thread_local_ptr<T>(fastboost::thread_specific_ptr<T>equivalent).Thread_token,this_thread_unique_token()(actually-unique thread IDs).Thread_local_obj_deinit_safe<T, Tag>.
flow::util::Basic_blobandBlob_with_log_context:- Bug fix: Containers of blobs (e.g.,
vector<Blob>) silently copied, instead of moving, blobs when relocating them, due to missingnoexcepts. #76 - Support stateful
Allocators (such asboost::interprocess::allocator); previously this did not compile. - Add optional allocate-and-zero in one step (
CLEAR_ON_ALLOCoverloads), which can be significantly faster than allocating and then zeroing. - Smaller
sizeof(). #84
- Bug fix: Containers of blobs (e.g.,
flow::util::Linked_hash_mapandLinked_hash_set:- Add move-semantics insertion (key need not be copyable).
- Perf and memory-use improvements: Key not stored twice per entry; open-addressed set instead of closed-addressed map.
- Remove
[pop_]front(),[pop_]back()methods (stylistically inappropriate for associative containers).
- Add misc utilities:
flow::util::Action_registry,Locked_proxy<Target, Mutex>,Default_init_allocator,construct_at(),default_init_at(),Span(alias), and arithmetic and pointer-math/alignment free functions.
- Add
- flow.log:
- Perf improvements at every log call site that passes the verbosity filter; and when writing message strings in ~all
flow::log::Loggers. (From internal use of thread-locality and faster lookups.) - Bug fix: Logging near thread death -- such as from the destructor of a
thread_localobject -- could hit undefined behavior, because certain thread-local flow.log facilities may by then be deinitialized. #116 - Add
flow::log::Log_context::set_logger(); andLog_context_mt, a variant whoseset_logger()is thread-safe. flow::log::Logger::this_thread_set_logged_nickname()(used also by much of flow.async): When the input nickname exceeds the Linux thread-name length limit (15 characters), and the function is to also affect the OS thread name (as fortopet al), that name is now truncated from the back, not the front. #71- The
Async_file_loggerworker thread's nickname now fits that limit.
- The
Async_file_loggerworker thread resets its core-affinity (see flow.async below), so it no longer inherits the creating thread's. #108
- Perf improvements at every log call site that passes the verbosity filter; and when writing message strings in ~all
- flow.async:
- Add
flow::async::reset_thread_pinning()andreset_this_thread_pinning(), which undo (on-demand) the default OS behavior of a thread inheriting its parent's setting. #108 flow::async::optimize_pinning_in_thread_pool()takes an optionalError_code*.
- Add
- NetFlow (
flow::net_flow):- Hardening: Use a CSPRNG for ephemeral ports, initial sequence numbers, and security tokens. Reported by Sebastián Alba Vives (@Sebasteuo). #112
- Hardening: Add configurable listen backlog (default 64) and limit on DATA cached in SYN_RCVD state (default 64Ki bytes). Reported by Sebastián Alba Vives (@Sebasteuo). #113
- Minor bug fixes (~no splash radius).
- Build/dependencies:
- Dependency bump: fmt v10.0.0 to 11.0.2. #104
- Boost.Random is now a required Boost library.
- Flow and Flow-like projects now fail the build if an export-worthy header is not actually exported.
- Significantly expand unit-test coverage: Many new tests (including for ~all new APIs above) and expand existing ones. #82
- GitHub CI pipeline:
- Conan 1 => 2 migration. #115
- Reduce pipeline run time: Dependency caching; parallelized core build step.
- Add "early-warning" jobs against newest (as opposed to only min-supported) dependency versions.
- Core-dump stack traces; LSAN suppressions; misc.
- Coding guide: Several additions.
- Comment and/or doc changes.
Full Changelog: v2.0.0...v3.0.0
API notes
- New/improved APIs:
- In
flow::util:statsub-namespace:- Operations on a stat-set (a
structof stat-members with an ADL-associateddeclare_stats()function):stats_to_ostream(),stats_reset(),stats_assign(),stats_aggregate[_one](),stats_aggregate_shards(),stats_reset_shard_aggregate(),stats_sum(),stats_field_names(),stats_mark_reset_state(),stats_since_reset_state(). - Per-stat helpers that work the same on plain and
atomicmembers:load(),store(),fetch_add(),fetch_sub(),update_hi_wmark(). Histogram_counter;Stat_set_list;Global_stats;Stat_name.
- Operations on a stat-set (a
- As pertains to thread-local state:
Thread_local_state_registry<T>: Maintains a thread-localTper thread, created on-demand viathis_thread_state()and deleted when its thread exits or the registry is destroyed, whichever happens first. To access all extant threads'Ts, callwhile_locked(task);task()receives the registry's map of extantTs.- At its core this is similar to
boost::thread_specific_ptr, except that utility deliberately holds no registry of extant threads. Use the registry functionality with care; the doc headers give advice.
- At its core this is similar to
Poll_flag: A single boolean flag, armed viaarm_next_poll()(typically from another thread) and both checked and disarmed viapoll_armed(), cheaply enough for the hottest of paths.Polled_shared_state<Shared_state>: Optional companion toThread_local_state_registry, for the pattern wherein one embeds aPoll_flagin each thread'sTand arms them all to signal a rare cross-thread request, which each thread checks cheaply along its fast-path.Shared_statecarries any state about the overall request, accessed viaPolled_shared_state::while_locked().Thread_local_ptr<T>: Semantically identical toboost::thread_specific_ptr<T>but with significantly fasterget().Thread_local_obj_deinit_safe<T, Tag>: Equivalent to a nakedthread_local T, but for non-trivially-destructibleTguards access to the object, yielding null if the object has been destroyed near thread exit.this_thread_unique_token()(and typeThread_token): Similar tothis_thread::get_id()but guaranteed never to recycle values.
- As pertains to
Basic_blob<Allocator>andBlob_with_log_context:- Stateful
Allocator(e.g.,boost::interprocess::allocator) support forBasic_blob. - New overloads that zero-initialize memory during buffer allocation:
reserve(),resize(), andresize()ing ctor, taking tag-typed valueCLEAR_ON_ALLOC. - Add
noexceptto move ctor and move assignment.
- Stateful
- As pertains to
Linked_hash_mapandLinked_hash_set:Linked_hash_map::insert()andoperator[]()overloads with move-semantics for keys and, where applicable, mapped-values;Linked_hash_set::insert()overload with move-semantics for keys.- Type alias members such as
KeyandHash.
Action_registry: A simple singleton template (with a tag parameter separating registries); code sites (particularly singleton initializers) can register actions (functors); other code can execute all actions in registration order, passing the same args to each.Locked_proxy<Target, Mutex>: Proxy-pointer class template for the execute-around-pointer idiom.Default_init_allocator: Allocator for STL-compliant containers that avoids zeroing things like PoDs andarray<>s.construct_at(), mimicking the C++20 STL facility of the same name;default_init_at(), reminiscent of C++23std::start_lifetime_as().- Arithmetic: New
constexprround_to_multiple();ceil_div()is nowconstexprand slightly more flexible. - Pointer-math/alignment free function templates:
is_power_of_two(),max_align_sz(),aligned_sz_of(),aligned_prefix_before(),after_aligned_prefix(). SpanandDYNAMIC_EXTENT: Aliases forstd::span-like ops.String_view::starts_with()andends_with()are nowconstexpr.setup_auto_cleanup()now takes its functor via move semantics.
- In
flow::log:Log_context::set_logger(): Change the deriver'sLogger*(not thread-safe).Log_context_mt: Variant ofLog_contextwhoseLogger*can be changed thread-safely viaset_logger(); the mutex also protects copy/move andswap().- Mutex-locked logging: New macros
FLOW_LOG_..._LOCKED()(lock, log, unlock); methodlog_while_locked()for a custom operation. New macroFLOW_LOG_SET_LOCKED_CONTEXT()is toFLOW_LOG_SET_CONTEXT()whatFLOW_LOG_..._LOCKED()is toFLOW_LOG_...(). - Unlike
Log_context, it has noget_logger()orget_log_component()(an unlocked accessor would defeat the purpose). - Usage/perf point: Each such log call site locks a mutex, even when the message does not pass the verbosity filter. Prefer to avoid such logging along fast-paths; the doc header gives advice.
- Mutex-locked logging: New macros
- In
flow::async:reset_thread_pinning()andreset_this_thread_pinning(): Reset the core-affinity (in particular as inherited from parent thread) of the given/calling thread to no preference, leaving migration decisions to the OS.optimize_pinning_in_thread_pool(): New optional argError_code*, making it compliant with the standard Flow error-emission pattern.
- In
flow::cfg:value_set_member_id_to_opt_name(): New optional argsep_replacement.
- In
flow::net_flow:- New
Node-level socket-optionm_dyn_accept_backlog_limit(default 64): AServer_socketrejects (with RST) any SYN once its count of half-opened plus not-yet-accepted connections reaches this limit, akin to thebacklogarg to Berkeley-socketlisten(). Changing it affects subsequently createdServer_sockets only. - New socket-option
m_st_rcv_syn_rcvd_data_q_cumulative_max_size(default 64Ki bytes) limiting the cumulative size of DATA payload cached for a half-opened (SYN_RCVD-state) connection. Previously these were limited only by the more general (and typically much more generous) receive-buffer limit.
- New
- In
- Breaking changes:
- Remove
flow::util::Linked_hash_{map|set}::front()andback()as well asLinked_hash_set::pop_{front|back}(). flow::util::Basic_blob<Allocator_t>::Allocator_rawalias renamed toAllocator.flow::log::Msg_metadata::m_call_thread_nicknameis now of typelog::Fixed_string(new alias forboost::static_string<128>) instead ofstd::string; logged thread nicknames are truncated to 128 characters. (It is a potential breaking change only for customLoggerimplementations. Change needed so that logging works even duringthread_localdeinit.)- Remove
flow::util::bind_nsnamespace alias. - Build/dependencies:
- Boost.Random library is now required.
- Flow-like projects (such as Flow-IPC) using Flow's core build script(s): Build now fails if an export-worthy
#includeee is not exported. Doc-only headers (such as concept docs) must be listed in new listDOC_ONLY_HDRS.
- Remove
Impl notes
flow::util::Thread_local_ptr<T>::get()faster thanboost::thread_specific_ptr<T>::get():- It wraps a
thread_specific_ptrbut also maintains its own per-thread index: athread_local boost::unordered_flat_mapkeyed by a unique 64-bit per-instance ID. Soget()touches onlythread_locals plus one open-addressed probe, versusthread_specific_ptr::get()'s OS-TLS-API call plus anstd::maplookup keyed bythis. - Trade-off:
reset()is slower, as it updates both. (Microbenchmark:get()~1.4x faster with 1 live instance, ~2x with 16 -- ours stays flat as instance count grows, whilethread_specific_ptr's degrades;reset()~1.8x slower.) - Near thread exit, once
thread_locals may be deinitialized, it falls back to thethread_specific_ptrpath.
- It wraps a
- flow.log perf:
- Three uses of
boost::thread_specific_ptrreplaced by C++ built-inthread_local; all are exercised at every log call site that passes the verbosity filter. - Per-call-site lookup in the thread-local map keyed by
Logger*uses a faster data structure. Config::output_component_to_ostream()(used by ~allLoggers when writing the message) uses a faster data structure for component lookups.
- Three uses of