Releases: StormByte-Suite/StormByte-Buffer
Release list
Version 2.0.0
[Summary]
StormByte Buffer is the byte-buffer module of the StormByte C++ suite.
It depends on StormByte Logger and StormByte System, which bring Base. This repository is not Base, Config, Crypto, Database, Logger, Multimedia, Network or System.
Public headers under StormByte/buffer/ cover FIFO, SharedFIFO, Ring, Producer/Consumer, Hopper, Sink, Bridge, Pipeline and StormByte::Buffer::IO (buffered binary sources and sinks). Octet payloads are StormByte::BinaryData. Byte lengths are StormByte::ByteSize. Hopper and Sink count items with StormByte::Size.
If you landed here from a release link and have not read the tree:
- What this module is, how to build it, and short examples: README.md
- License: GNU Lesser General Public License version 3 or later, LICENSE
Added
option(BUILD_SHARED_LIBS "Build shared libraries" ON)in the project root. Shared is the default so a consumer can redistribute without triggering LGPL static-link obligations. Static is opt-in (-DBUILD_SHARED_LIBS=OFF). CI passes-DBUILD_SHARED_LIBS=ON. Third-party StormByte pins passENABLE_TEST=OFF.- Nested
Parameterson all buffered reader/writer levels, with knobsReadAhead,MaxMemory,MaxWait,WriteChunkandBackPressure. Omitted knobs retain the previous defaults; omitting all device knobs makesSetup()probe. Brace-init and namedParametersare supported. Variadic knobs resolve in the caller underSTORMBYTE_FORCE_INLINE; the DLL receives only numbers and a probe flag. BufferedReaderpage cache and logical seek. Consumed bytes remain in RAM up toMaxMemory; garbage collection evicts farthest fromTell.SeekupdatesTellimmediately, avoids moving the origin on a cache hit, and resumes prefetch with oneOriginSeekwhen a later read leaves the cached range.Tellnever lies.BufferedWriterdirty-page cache and logical seek. Writes are lazy untilMaxMemory,FlushorClose; nearby corrections and far-future islands are supported while memory allows. Eviction prefers the oldest dirty page behind the origin cursor.Seekis logical; materializing a page (eviction, flush or close) moves the origin.- Layered telemetry in
StormByte::BufferandStormByte::Buffer::IO. Read/write counters hold delivered/accepted bytes; IO telemetry adds cache/origin/seek/wait counters.MeanRateis the caller-visible effective rate (ByteSize/s), including cache hits, not device throughput. Telemetry handles areconst StormByte::Safe::Shared<…>, stable for the life of the office; accumulators do not reset on close. Public writerFlushand the flush inClosecount toward the rate; internal worker/GC drains do not. Flattening providesoperator StormByte::Safe::Stringout of line and caller-sideSTORMBYTE_FORCE_INLINE operator std::string(). BufferedReader::Available(). Contiguous cached bytes atTell. Does not callOriginPull/OriginSeekand does not wait for prefetch.StormByte::Buffer::Pumper. Takes aBridgeby move and runsPassthroughon a worker until EoF or failure. Starts in the constructor; the destructor joins. NestedParameterswith knobsChunkandHighWater.Chunk0is automatic cycle size, not Bridge “current contents”.HighWaterapplies to the input only: omitted =0if the source is IO, otherwise the backend default (constexpr in the PIMPL.cxx); explicit0= no Pumper cap (intended when the IO source already limits itself). Non-IO sources are unbounded by design.Togglepauses/resumes.Cancelis terminal (Failed, no restart). Telemetry is forwarded from the owned Bridge.StormByte::Buffer::Pipe(pipe.hxx/pipe.cxx). Abstract stream stage (StormByte::Safe::Clonable+StormByte::Safe::Unique<Pipe>). Copyable and movable (special members out of line).Run(ReadOnly&, WriteOnly&, const Shared<Logger::Log>&).CloneandMoveare public and must be implemented by the leaf withUnique::MakePointerin the leaf TU.
Changed
- Breaking: Port Buffer to StormByte Base 2.0.0. Owned text is now
StormByte::Safe::String/Safe::WString; pointer and clonable APIs useStormByte::Safe; Buffer telemetry derives from BaseStormByte::Telemetryand measures operations with its named clocks; Buffer exceptions accept Base-ownedSafe::Stringmessages. - Breaking:
StormByte::Buffer::Datais gone. Octet payloads areStormByte::BinaryDatafrom Base.data.hxx/data.cxxandDataTestsare removed. - Breaking: byte counts are
StormByte::ByteSize(FIFO,Ring,SharedFIFO,Producer/Consumer,Bridge,Pipeline,IO).Hopper<T>andSink<T>count items withStormByte::Size(Capacity,Size,Buckets,Select). - Breaking:
AvailableBytes()isAvailable(). The return type is alreadyStormByte::ByteSize. - Breaking:
ExternalReader,ExternalWriter,ExternalBufferReaderandExternalBufferWriterare removed.Bridgeborrows non-IOReadOnly/WriteOnlytips directly; those buffers must outlive it. IO leaves remain owned by move. - Breaking:
Pipeline::PipeFunction(std::functionover External reader/writer types) is gone. A stage is a user leaf ofPipe.Pipeline::Add(const Pipe&)clones onto Base's heap and does not touch the caller;Pipeline::Add(Pipe&&)takesMove(). There is no boxing of callables and no publicUnique<Pipe>add.Pipelineis stream buffers only (ReadOnly/WriteOnly); IO joins throughBridge/Pumper.Process(Consumer, Shared<Logger::Log>, ExecutionMode)— mode last. - Breaking:
BufferedLocationReaderandBufferedLocationWritersit between the engines and the file leaves. A location is file-like: named byLocation()(StormByte::Safe::String, owned by Base), always seekable and sized. Path-onlySetup()lives here.Device()and the pureOriginDevice()returnStormByte::Safe::Shared<StormByte::System::Device>instead ofSystem::Deviceby value. A leaf may now hand out aSystem::Devicesubclass (for example a NIC device whose accessor is not a filesystem path) and the dynamic type survives, so overriddenThroughput()/Window()are honoured and the caller can keep the object alive. Build the owner withStormByte::Safe::Shared<StormByte::System::Device>::MakePointer<Leaf>(…)so the object lives on Base's heap and crosses the DLL boundary safely.- New protected
virtual bool OriginDeviceUsable(const StormByte::Safe::Shared<StormByte::System::Device>&) const noexcept. The default is the previous behaviour (non-empty owner andoperator bool()true, which probes the stored path). A leaf whose identifier is not a filesystem path overrides it and never reaches the non-virtual path probe. An empty owner is always unusable. Setup()staysfinal, callsOriginDevice()once, asksOriginDeviceUsable()and only then appliesWindow()on the dynamic object. When the device is not usable the per-leaf defaults (ReadAhead, orWriteChunk/BackPressure/MaxMemory) are kept. The device is never copied or sliced to the base type.
- Breaking:
BufferedFileReaderandBufferedFileWriterarefinal.CreateDevice()is gone.Path()(const String&) andLocation()(IO::Location) are set onBufferedReader/BufferedWriterand do not change. A file leaf passesLocation::Local. A socket on the lower layer can passLocation::Remote. The file leaves keep the plainSystem::Deviceand the real path probe, so their windows and defaults are unchanged. - Breaking: IO constructors no longer take positional windows (
read_ahead,max_memory,write_chunk,back_pressure,max_wait). One constructor per leaf: path plus that class’sParameters(default{}= probe). Explicit zeros stay zeros; they do not probe. - Breaking:
Buffer::ExceptionusesException::Path{"Buffer"}.what()isStormByte.Buffer: message;ReadErrorandWriteErroruseStormByte.Buffer.ReadandStormByte.Buffer.Write. Buffer-specific destructors are defined in this module. - Breaking:
Bridgeis a manual transfer again, not a worker. PublicPassthrough(ByteSize, Operation)is the only transfer;Operation::{Blocking, NonBlocking}applies to the read tip; writeTryAgainis retried until that call completes.n == 0is current contents (Available()). Non-IO tips areReadOnly&/WriteOnly&. IO tips are stolen by move as the concrete leaf.Failed()is sticky. Continuous pumping isPumper. - Reader
Seekis no longer “alwaysOriginSeek”. A cache hit is O(1) on the origin. A miss still costs a real seek plus whatever the device does. - Writer
Seekexists and is part of the public contract. It is not guaranteed O(1) when the target is not in the dirty map or when eviction must drain pages first. - Writer contract: lazy write up to
MaxMemory. More random access needs moreMaxMemoryor islands get evicted (a real write + seek). - Nested
BufferedReader::Telemetry/BufferedWriter::Telemetrystructs are gone. Counters live on the Shared objects; getters, not public fields. LockFreeRing::FrontSpanreturns a snapshot copied under the wait mutex so a concurrentGrowcannot invalidate the pointer the drain worker is pushing.- Origin I/O on the writer (
OriginSeek/OriginPush/OriginFlush/OriginOpen/OriginClose/OriginTruncate) is serialized against the drain worker.Flushwaits until the ring is empty and the worker has published the origin cursor (!m_drain_run). - Dual license layout:
LICENSEis the short header text;COPYING.LGPLv3is the LGPL text.
Fixed
- Writer drain vs
Grow:FrontSpanno longer aliasesm_storagewhile the pro...
Version 1.4.0
[Summary]
StormByte Buffer is the byte-buffer module of the StormByte C++ suite.
It depends on StormByte Base and optionally StormByte Logger. This repository is not Base, Config, Crypto, Database, Logger, Multimedia, Network or System.
Public headers under StormByte/buffer/ cover FIFO, SharedFIFO, Ring, Producer/Consumer, Hopper, Sink, Bridge, Pipeline and StormByte::Buffer::IO (buffered binary sources and sinks).
If you landed here from a release link and have not read the tree:
- What this module is, how to build it, and short examples: README.md
- License: GNU Lesser General Public License version 3 or later, LICENSE
Added
StormByte::Buffer::IO. Buffered binary sources and sinks, separate from FIFO / Ring / Hopper. Public surface:Status,State,Result,ToString,BufferedReader,BufferedWriter,BufferedFileReader,BufferedFileWriter.IO::Backendis the PIMPL and is not a public include.Status/Result/State.Ok,End,Error,Failed,TryAgainplus a bytecount.TryAgainis backpressure or a boundedMaxWait.State:Idle,Missing,Directory,Permission,NotWritable,Fault,Unavailable.constexpr ToStringforStatusandState.BufferedReader. Public base for a binary origin. Leaves implementOriginOpen,OriginClose,OriginPull,OriginCanSeek,OriginSeek,OriginHasSizeandOriginSize. OptionalSetup()runs once fromOpenbeforeOriginOpen. Construction isUnavailable; a successfulOpenisIdle.Closeis idempotent;Openis not.operator boolis Idle and notEoF.- Reader
Read/Peekinto aFIFOor a writablestd::span<std::byte>. Destination overwritten only onOk/Endwith a non-zero count. Empty span is{Ok, 0}. FIFOn == 0serves the cached span atTell.MaxWait0mswaits without limit. - Reader
Seek/Tell/IsSeekable/IsSized/Size. Absolute or relative only. End-relative isSeek(*Size() + off, Absolute)when sized. SeekableSeekalways callsOriginSeek, including a cache hit. Non-seekableSeekisFailedand does not call the hook. Seek is not O(1). Cache is a map of owned spans; overlap merges;MaxMemoryevicts farthest fromTell;0stores nothing and still serves from the origin. Prefetch stops onSeekand on move (Rebind); the nextRead/Peekrequests it again. BufferedFileReader.ifstreamleaf, seekable and sized. Path-only constructor probes device throughput atSetupand setsReadAhead(window clamped 16 KiB–1 MiB) withMaxMemory1 MiB. Explicit(path, read_ahead, max_memory)keeps those knobs. Does not open in the constructor.BufferedWriter. Public base for a binary sink. Leaves implementOriginOpen,OriginClose,OriginPush,OriginFlushandOriginTruncate. OptionalSetup()andWillWrite. NoSeek.Tellis bytes accepted sinceOpenorTruncate.Closeflushes then closes; a flush failure isFault.- Writer
Write(const FIFO&),Write(FIFO&)andWrite(std::span<const std::byte>). Atomic.WriteChunkandBackPressure(in chunks): either knob0is direct; both> 0use an SPSCLockFreeRingcapped atBackPressure * WriteChunkbytes. Overflow isTryAgain.Dirty()is unread ring bytes.Flush()drains the ring and callsOriginFlush. BufferedFileWriter.ofstreamleaf, binary append. Creates the file when the parent exists (nomkdir -p). Path-only constructor probes the device atSetupand setsWriteChunkplusBackPressure4. Explicit(path, write_chunk, backpressure)keeps those knobs.Truncateoverwrites.- Device throughput probe (private): Linux / Windows / macOS classification (HDD, SATA SSD, NVMe gen, USB, network at 80 % of NIC). Nominal rates, not a benchmark. Device knobs have no setters;
MaxMemoryandMaxWaitstay settable. LockFreeRing::FrontSpan,ConsumeandWrite(std::span<const std::byte>).ExternalWriter::Occupied.Bridgepumps anyExternalReader/IOreader into anyExternalWriter/IOwriter.Drainrespects sink backpressure. Worker auto-drains; publicPassthroughis gone.high_water == 0means no extra occupancy cap. The worker starts, including whenhigh_wateris 0. Pause is onlyDrainer(Toggle).- Two-argument
Bridgeconstructors forBufferedWritersinks:
Bridge(const IO::BufferedReader&, IO::BufferedWriter&)and
Bridge(ExternalReader&, IO::BufferedWriter&). No occupancy cap at
the Bridge layer. Same pump path ashigh_water == 0. Intended for
BufferedFileWriter(WriteChunk / BackPressure already cap Dirty).
Pairings into FIFO / SharedFIFO / Ring / Producer keep the
three-argument constructor.
Removed
Sink::BindandSink::Bind(int, Sink&). Wire withTo(key)/>>/<<.
Tests
BufferedFileReaderTests. Fixtures undertest/files/. SpanRead/Peek,Tell,Seek(absolute, relative, end viaSize, cache hit,MaxMemory0), path-only vs explicit constructors, move with prefetch stopped.BufferedFileWriterTests. Temp files viaStormByte::System::TempFileName. Direct(path, 0, 0), path-only device knobs, Dirty / Flush / BackPressure / Truncate / move.BufferedMeteredFileTests. Selective override example (BytesRead/BytesWritten).- Bridge coverage for pipe close-while-started,
high_water0, and the two-argument writer ctors (test_io_uncapped_ctor,test_buf_to_io_uncapped_ctor).
Version 1.3.0
[Summary]
StormByte Buffer is the byte-buffer module of the StormByte C++ suite.
It depends on StormByte Base and optionally StormByte Logger. This repository is not Base, Config, Crypto, Database, Logger, Multimedia, Network or System.
Public headers under StormByte/buffer/ cover FIFO, SharedFIFO, Ring, Producer/Consumer, Hopper, Sink, Bridge and Pipeline.
If you landed here from a release link and have not read the tree:
- What this module is, how to build it, and short examples: README.md
- License: GNU Lesser General Public License version 3 or later, LICENSE
Added
Sink::Keys,Sink::Buckets,Sink::Contains,Sink::Empty(key),Sink::EoF(key)andSink::Ready(key). Query only. Missing key:Emptyis true,EoF/Ready/Containsare false,Bucketsis the wired count.Sink::Pop(int key). Reads that hopper only. Waits until the key is wired or the Sink is closed. Empty hopper returns defaultT(same asHopper::Pop). Does not interpret the key.Hopper::Writers,Hopper::ReadyandHopper::Front.Frontcopies the next item and does not dequeue; requiresstd::copy_constructible<T>(shared_ptr). Not a deep copy of the payload.Writersis the live writer count (starts at 1).
Tests
test_hopper_front_peek,test_hopper_writers_and_ready.test_sink_pop_key,test_sink_query_unwired,test_sink_query_wired.- Hopper and Sink test files ordered by section name, then by test name.
Version 1.2.0
[Summary]
StormByte Buffer is the byte-buffer module of the StormByte C++ suite.
It depends on StormByte Base and optionally StormByte Logger. This repository is not Base, Config, Crypto, Database, Logger, Multimedia, Network or System.
Public headers under StormByte/buffer/ cover FIFO, SharedFIFO, Ring, Producer/Consumer, Hopper, Sink, Bridge and Pipeline.
If you landed here from a release link and have not read the tree:
- What this module is, how to build it, and short examples: README.md
- License: GNU Lesser General Public License version 3 or later, LICENSE
Added
Hopper::UnnotifyandSink::Unnotify.Notify(cv&)does not own the
condition variable. After wiring, the Hopper outlives the consumer; the
consumer mustUnnotifybefore that CV is destroyed so a later producer
Eofdoes not signal a freed object.SignalConsumeris a no-op when
the pointer is null.Sink::To(key),Sink::operator>>andSink::operator<<. Same wiring
asBind/Bind(key)(writer, reader, co-writer).Bindstays as a
[[deprecated]]wrapper for one or two releases.Hopper::operator<</Hopper::operator>>anditem >> hopper. Same
asPush/Pop. Those methods stay.Pipeline::Processscopes a non-null logger withScope("Buffer/Pipeline")
before handing it to stages.%cidentifies this module without using the
thread-local component stack. Nestedlog->Scope("Decode")inside a stage
becomesBuffer/Pipeline/Decode(orMultimedia/Buffer/Pipeline/Decode
if the caller already scoped a parent). Pass the application or parent-module
logger; do not pre-scopeBuffer/Pipeline.
Changed
- Optional Logger pin is 1.2.0
(Scopeand hierarchical components).
Tests
test_hopper_unnotify_before_cv_dies,test_hopper_notify_after_unnotify,
test_hopper_stream_members,test_hopper_stream_item_into.test_sink_unnotify_before_cv_dies,test_sink_stream_operators.
Existing Sink tests useTo/>>/<<instead ofBind.
Version 1.1.2
[Summary]
StormByte Buffer is the byte-buffer module of the StormByte C++ suite.
It depends on StormByte Base and optionally StormByte Logger. This repository is not Base, Config, Crypto, Database, Logger, Multimedia, Network or System.
Public headers under StormByte/buffer/ cover FIFO, SharedFIFO, Ring, Producer/Consumer, Hopper, Sink, Bridge and Pipeline.
If you landed here from a release link and have not read the tree:
- What this module is, how to build it, and short examples: README.md
- License: GNU Lesser General Public License version 3 or later, LICENSE
Deprecated
Sink::Bind(both overloads). See Unreleased TODO.
Fixed
Sink::Bind(key)of a hopper this Sink already holds attaches the other Sink as a co-writer.Sink::Eofthen closes that hopper only when the last writer closes, so extra producers can stillPush. No new public methods.Sink::Bind(key)does not add a writer if the other Sink already writes that hopper. A second Bind of the same producer no longer leaves the hopper open after oneEof.test_sink_rebind_same_writer_eofwaits up to 1s for that EoF (the remuxer hang).
Version 1.1.1
[Summary]
StormByte Buffer is the byte-buffer module of the StormByte C++ suite.
It depends on StormByte Base and optionally StormByte Logger. This repository is not Base, Config, Crypto, Database, Logger, Multimedia, Network or System.
Public headers under StormByte/buffer/ cover FIFO, SharedFIFO, Ring, Producer/Consumer, Hopper, Sink, Bridge and Pipeline.
If you landed here from a release link and have not read the tree:
- What this module is, how to build it, and short examples: README.md
- License: GNU Lesser General Public License version 3 or later, LICENSE
Changed
- Bundled StormByte Logger is 1.1.1 (and transitively StormByte Base 1.1.1). The declared requirement stays Logger 1.1.0 or newer.
Version 1.1.0
[Summary]
StormByte Buffer is the byte-buffer module of the StormByte C++ suite.
It depends on StormByte Base and optionally StormByte Logger. This repository is not Base, Config, Crypto, Database, Logger, Multimedia, Network or System.
Public headers under StormByte/buffer/ cover FIFO, SharedFIFO, Ring, Producer/Consumer, Hopper, Sink, Bridge and Pipeline.
If you landed here from a release link and have not read the tree:
- What this module is, how to build it, and short examples: README.md
- License: GNU Lesser General Public License version 3 or later, LICENSE
Added
Hopper<T>— single-producer single-consumer (SPSC) typed queue (Type::MoveConstructible) with optional capacity ceiling, non-blockingPop,Pushwait when full,Eofsignaling, consumer condition variable notification (Notify), and automatic null item discarding forType::SmartPointertypes.Sink<T>— integer key map ofHopper<T>buckets supportingBindhopper sharing, terminal producerDrainmode,Readycheck, Round-Robin or customSelectindex chooser popping, and per-keyCapacity,Size, andFullqueries.- Header implementation files
hopper.txxandsink.txxinstalled alongside public headers (*.txxincmake/install.cmake).
Changed
- Updated dependency requirement to StormByte Logger 1.1.0 (and transitively StormByte Base 1.1.0).
- Routed range and iterator byte APIs through StormByte Base type concepts (
Type::ByteInputRange,Type::ByteInputIterator,Type::SentinelFor,Type::SameAs) instead of local standard-library constraints. - Limited
Hopper<T>andSink<T>null-item filtering toType::NullablePointerso only pointer-like values that can be tested for emptiness use the!itempath. - Documented
Sink::EoF()contract: with hoppers, evaluatestruewhen all hoppers are empty andHopper::EoF()istrue, even if thisSinkitself did not callEof(); binding a new key afterEoF()returnedtruemay returnEoF()tofalse.
Fixed
- Ported Buffer exceptions to
StormByte::Component, preventing format-string overload ambiguity and correctly prefixingReadErrorandWriteErrormessages. - Moved virtual override definitions and destructors to compiled translation units so shared-library builds export stable vtables, RTTI and non-virtual thunks for GCC consumers, with polymorphic consumer coverage in each owning class test.
- Closed
Sinkand marked hoppersEofatomically underm_mutexinSink::Eofand checked closed state andconsumer.m_consumerunder lock inSink::Bindto prevent concurrentBindcalls from creating un-marked hoppers or skipping consumerNotify. - Marked
Sinkclosed in destructor to safely unblock threads waiting inPushandPop.
Version 1.0.0
[Summary]
StormByte Buffer is the byte-buffer module of the StormByte C++ suite.
It depends on StormByte Base and optionally StormByte Logger. This repository is not Base, Config, Crypto, Database, Logger, Multimedia, Network or System.
Public headers under StormByte/buffer/ cover FIFO, SharedFIFO, Ring, Producer/Consumer, Bridge and Pipeline.
If you landed here from a release link and have not read the tree:
- What this module is, how to build it, and short examples: README.md
- License: GNU Lesser General Public License version 3 or later, LICENSE
Initial public release of StormByte Buffer.
Added
- Hierarchical interfaces:
Generic,ReadOnly,WriteOnly,ReadWrite FIFO— grow-on-demand byte buffer (single-threaded)SharedFIFO— thread-safe FIFO with blocking reads/extractsRing— concurrent ring (shared_mutex, many-to-many)Producer/Consumer— write/read handles overRingExternalReader/ExternalWriter— I/O adaptersBridge— chunked passthrough with optional flush-on-destroyPipelinewithExecutionMode:Sync,Async,Parallel(combinable)- Private
LockFreeRing— SPSC intermediates between pipeline stages - Lifecycle:
Close(),SetError(),EoF(),IsReadable(),IsWritable() - Non-destructive
Read/Peekand destructiveExtract, plus*UntilEoF - Seek, Drop, Clean, Clear, HexDump
- Unit tests (FIFO, SharedFIFO, Ring, Producer/Consumer, Bridge, Pipeline)
- Project version read from the
VERSIONfile - CMake 3.28 floor
Notes
FIFOis not thread-safe; useSharedFIFOorRingfor concurrent access.LockFreeRingis private and only safe under single-producer / single-consumer use.- Pipeline stages must
out.Close()orout.SetError()when finished. - Needs a C++26 compiler and StormByte Base ≥ 1.0.0.