Revision history for Linux-Event 0.118 2026-11-01 - Add Stream->sendfile($file, offset => ..., length => ...) for established plain TCP and Unix-domain socket Streams. File ranges share the native ordered output queue with write() and obey existing backpressure, output limits, deadlines, graceful end, and close behavior. Keep the caller's file position unchanged and retain an owned close-on-exec duplicate so the caller may close its filehandle. - Reject TLS and other non-plain transports, pending connections, and invalid file ranges rather than silently copying or reframing data. Preserve the ordinary byte-write hot path and bound mixed file output to 64 KiB per readiness turn for Loop fairness. Add regression tests for ordering, callbacks, lifecycle, managed fork, and file descriptor cleanup, plus byte-verified TCP benchmarks and public documentation. - Add Loop->defer_fork() so socket, timer, and other event callbacks can request a managed fork without forking inside native dispatch. Reuse the existing resource-aware share/clone/move dispositions and child reconstruction handshake. Parent and child completion callbacks run only after the native driver has returned to a quiescent point. - Return a cancelable one-shot request handle, support on_error for deferred failures, preserve explicit stop priority, and discard pending fork requests inherited by a child to prevent unintended repeated forks. Support run(), run_for(), run_once(), and poll() with the same application-facing API. Ordinary Loop->fork() remains quiescent-only. - Keep epoll dispatch in native XS. Add targeted deferred-fork regression coverage and an isolated public/native driver overhead benchmark. Update examples and documentation for callback-triggered forking. 0.117 2026-09-24 - Rewrite public POD with clearer constructor placement, callback signatures, lifecycle explanations, and practical examples. Keep SYNOPSIS examples compilable and validate code separately from prose. - Exclude generated Inotify build files from distribution packaging. - Make IO::TTY borrow supplied terminal handles by default so wrapping STDIN/STDOUT does not make TTY close destroy the process standard handles. Capture and temporarily apply nonblocking/close-on-exec descriptor state, never close caller-owned handles on explicit close, directional close, graceful end, or EOF, restore captured flags when the complete borrowed TTY becomes terminal or detaches, and add owns_handles => 1 for explicit ownership. Preserve Pipe and Stream ownership semantics. - Add an explicit Loop-aware fork contract with strict per-resource dispositions. Loop->fork() is quiescent-only, rejects unsupported combinations before the syscall where foreseeable, gives the child a fresh epoll/timer reactor, and makes unlisted resources parent-only. Listener supports share/move, Timer supports clone/move with preserved absolute deadlines, Inotify supports independent clone or inherited move, and established plain socket Stream supports move. Moved parent objects become terminal/inert. A parent/child reconstruction handshake prevents parent-side move teardown until the child is ready. - Make accidental reuse of an inherited Loop after ordinary CORE::fork() fail by process ownership checks across driving, registration, introspection, statistics, and tuning operations. Deferred queues are not inherited. Signal services are dismantled child-side without modifying the parent's inherited signalfd state, and idle resolver worker services are quiesced before managed fork; active resolution is rejected. - Add Linux::Event::Kernel::Inotify with explicit Loop attachment, logical child Watch objects, decoded immutable Event values, named per-event callbacks plus on_event, parent-level overflow/error handling, shared-inode watch fan-out, rename-cookie preservation, reentrant-safe cancellation/close, and bounded burst dispatch through Loop->defer(). Detached watches remain specifications until attachment; live watch installation and failed attachment are synchronous and transactional. - Add Loop->defer() for owner-interpreter, non-reentrant next-turn work. Deliver eligible callbacks FIFO, force work queued during a deferred drain to a later turn, provide an opaque cancelable one-shot handle, retain pending work at Loop scope, preserve later work across callback exceptions, and bound each drain to 1,024 queue entries. Use a lazy private eventfd so deferred work participates in poll_fd()/poll() foreign-loop integration without becoming a cross-thread callback queue. 0.116 2026-09-20 - Allow transition_to() to retire a live native consumer into an ordinary Perl Stream input sink while preserving unread ordered input natively until the target consumes it. Reuse provider flush/retain lifetime settling, support reentrant transition and target close safely, preserve exact-once ordered tail delivery across pause/resume, and keep ordinary-to-native live transitions explicitly rejected. 0.115 2026-09-19 - Make raw native-consumer input safe when application callbacks close the Stream reentrantly. Terminal teardown owns the cleared native buffer, so the core no longer applies a returned consumed count afterward. Preserve nonterminal provider-changing transition_to() accounting: consume the source prefix, then re-drive the retained tail through the replacement. - Generalize transition_to() so one native consumer provider can hand the live ordered-byte stream to another provider without surfacing unread tail bytes through Perl. Pre-create the target context, settle source flush debt, defer source destruction across active provider frames/host retains, and re-drive preserved native input through the target. Keep adding/removing native-consumer mode during a live transition rejected. - Add the supported foreign-loop integration boundary: poll_fd() exposes the Loop-owned epoll descriptor as a borrowed readiness fd, and poll() performs exactly one nonblocking dispatch turn. Keep adapters outside core and preserve dependency-free shipped contract coverage. - Bound the shared ordered-byte read drain by default with read_budget_bytes => 65_536 so continuously replenished Stream, Pipe, or TTY input yields back to Loop dispatch instead of starving timerfd and other ready descriptors. Explicit read_budget_bytes => 0 remains the opt-in drain-until-EAGAIN mode. Preserve the fairness reproducer, payload sweep, raw benchmark evidence, and KEEP decision record. - Generalize the append-only native consumer ABI v1 with an optional raw-input capability for protocol engines that cannot use a built-in native framer. Providers may consume a borrowed contiguous native (data, length) window before payload bytes become a Perl SV; unconsumed tails remain in the shared native input buffer across later reads and pause/resume. Original ABI-v1 providers remain compatible. - Keep protocol subclasses free to define public close() semantics by routing involuntary Stream teardown through the private terminal-close primitive instead of virtual close() dispatch. - Cover adopted socket configuration failure, accepted Stream setup failure, and on_accept failure with regressions proving subclass close() overrides are bypassed while descriptor cleanup and on_close behavior remain intact. - Preserve LES_CONSUMER_CLOSE virtual dispatch because that ABI status is an explicit semantic request to close the host through normal lifecycle. 0.114 2026-09-13 - Enforce the documented transition_to() invariant across all public ordered-byte resource kinds. Pipe, TTY, and connected SOCK_STREAM subclasses may transition only to another protocol class for the same underlying kind. - Add a complete cross-kind rejection and same-kind success regression matrix. Failed transitions preserve the source class, protocol descriptor, and native state. - Record the remaining foreign-loop integration, deferred-callback, post-fork Loop-contract, and inotify work on the roadmap to 1.000. 0.113 2026-09-12 - Replace the internal Socket Stream multiple-inheritance diamond with a single behavioral parent, the ordered-byte engine. Socket descriptors, connection acquisition, configuration, addresses, and transports remain explicitly composed facilities. Document and test ordinary subclass-owned instance state, and organize Stream implementation code into demarcated constructor, accessor, method, and private-helper sections. - Replace Listener stream_class and flat accepted-Stream constructor templates with one resolved stream => {...} recipe. Listener bind/listen/ accept policy remains top-level while class, data, tuning, TLS, and Stream callbacks belong to the generated-connection recipe. - Rename the ordered-byte class tuning hook from stream_options() to stream_tuning(), add live $stream->tune(...), and keep effective mutable values in native per-Stream state with no new steady-state Perl lookup. - Define deterministic live tuning transitions for batching, watermarks, hard output/input limits, and established idle/read/write deadlines. - Make accepted TLS acquisition-time policy selected by stream->{tls} rather than Stream class identity. Listener construction validates deployment policy and prepares one reusable server SSL_CTX; accepted connections allocate independent SSL state from that prepared context. - Add regression coverage for recipe validation and precedence, live tuning, plain/TLS reuse of one Stream class, prepared TLS context cloning, and lowered max_pending_bytes/max_buffer grandfathering behavior. - Add a dedicated accepted-TLS setup benchmark alongside the existing steady-state encrypted-I/O microbenchmark, and update public POD, examples, README, and architecture documents to the new API. - Repair remaining shipped Listener documentation and benchmark examples that still used the removed stream_class/flat callback API, and add a regression guard against reintroducing the retired configuration syntax. 0.112 2026-09-05 - Extend first-class cached constructor callbacks to Kernel::Event, Kernel::Timer, Kernel::Signal, Kernel::Process, and IO::Sock::Dgram. Public leaves can now be used directly while subclass methods retain the cached fast path and may be overridden per object. - Document subclassing prominently as the declarative home for native framers, TLS, socket policy, and Stream, Datagram, and Process tuning. Add live delivery, override, lexical-retention, validation, and terminal callback-release tests for the expanded constructor API. - Add first-class constructor callbacks for ordered-byte input and lifecycle events on Pipe, TTY, connected Stream, and accepted Stream objects. Constructor callbacks override same-named class methods for that instance. - Cache the effective raw, framed, and batched input callback directly in native stream state, preserving direct CV dispatch and compatible instance callbacks across protocol transitions. - Let Listener constructors provide one shared callback set for every accepted Stream, without allocating per-connection wrapper closures. - Add lifecycle, transition, teardown, Listener propagation, and callback retention coverage plus permanent construction, raw-dispatch, and framed-dispatch regression benchmarks. - Add a high-level Stream comparison harness for raw and delimiter-framed Linux::Event, AnyEvent, UV, IO::Async, and Mojo adapters. Keep this optional-dependency benchmark outside the CPAN distribution and installation test suite. - Document callback signatures, mode validation, class-policy boundaries, Listener template reuse, and cached-CV dispatch throughout public POD and design documents. Compile every public POD SYNOPSIS and execute the Pipe and connected-Stream callback examples during testing. 0.111 2026-09-04 - Complete the coherent private-core refactor behind the IO/Kernel public API. Remove the retired top-level Stream, Socket, Listener, Datagram, Timer, Signal, Wakeup, and Process implementation packages instead of retaining a second historical class hierarchy. - Move shared ordered-byte mechanics to Linux::Event::_ByteStream, socket specializations to Linux::Event::_Socket::*, and kernel-native facilities directly beneath their Linux::Event::Kernel::* classes. - Rename the ordered-byte and eventfd extension roots to xsbytestream and xsevent, and align native package symbols and descriptors with the coherent private taxonomy without adding Perl dispatch to hot paths. - Preserve the concrete IO::Pipe, IO::TTY, IO::Sock::Stream, IO::Sock::Listener, IO::Sock::Dgram, and Kernel::* application contracts, including framing, batching, deadlines, TLS, connection acquisition, and the versioned native consumer ABI. - Enforce protocol-transition resource boundaries using the new hierarchy; Pipe protocols and connected socket-stream protocols cannot transition into one another even though both share the ordered-byte engine. - Repair transformed callback, descriptor, benchmark, diagnostic, lifecycle, and native-consumer test paths, and add regression coverage for both sides of the Pipe/socket transition boundary. - Update architecture guides, POD, examples, benchmarks, manifests, metadata, and taxonomy tests to describe the finished design. Remove the one-shot migration workflow/scripts and obsolete historical-wrapper overhead gate from the release distribution. 0.110 2026-09-03 - Replace the misleading top-level Stream, Socket, Listener, Datagram, Timer, Signal, Wakeup, and Process public model with semantic IO and Kernel leaves. Application data I/O now uses Linux::Event::IO::Pipe, IO::TTY, IO::Sock::Stream, IO::Sock::Listener, and IO::Sock::Dgram; kernel notification/state objects use Linux::Event::Kernel::Timer, Kernel::Signal, Kernel::Event, and Kernel::Process. - Treat IO and Kernel as namespace categories rather than generic public base objects. Keep shared implementation mechanics behind private _IO, _ByteStream, and _Socket boundaries so public inheritance does not imply false Linux relationships. - Make Linux SOCK_STREAM and SOCK_DGRAM type names explicit in the socket namespace while keeping AF_INET, AF_INET6, and AF_UNIX as address-family configuration. Listener remains a distinct public accept-oriented role for listening SOCK_STREAM sockets. - Preserve the native ordered-byte hot path for Pipe, TTY, and stream sockets. The shared engine supports one handle, split read/write handles, read-only or write-only operation, framing, batching, backpressure, output limits, established deadlines, protocol transitions, and directional lifecycle without adding a public generic byte-stream class. - Validate Pipe handles as pipes/FIFOs and TTY handles as terminals/PTYS before attachment. Add tested interactive STDIN/STDOUT terminal usage and pipe-oriented framing examples. - Move connection, address, socket-option, kernel half-close, and TLS semantics to IO::Sock::Stream. Outbound connect retains one object through asynchronous resolution, connection, optional TLS readiness, established I/O, and close. Listener stream_class now names an IO::Sock::Stream subclass. - Keep datagrams packet-oriented under IO::Sock::Dgram. Kernel-provided packet boundaries, per-packet peers, truncation detection, whole-packet queues, and UDP/Unix datagram policy remain separate from byte framing. - Present eventfd through Kernel::Event with on_event while retaining the proven native eventfd implementation privately. Timer, Signal, and Process likewise retain their timerfd, signalfd, and pidfd-backed engines behind the corrected public Kernel leaves. - Make Linux::Event::Framer the public native-framing declaration surface for every ordered-byte leaf. A bare module import is valid for extension authors, and declare_native_consumer() provides the stable declaration boundary for separate XS integrations such as Linux::Event::Async without depending on the historical Stream package. - Retain the versioned native framed-message consumer ABI while hardening pause/resume, terminal flush ordering, provider-frame lifetime, construction failure cleanup, transition safety, and reentrant close. Add optional read_budget_bytes fairness while preserving unlimited drain as the default. - Keep historical Stream XS package/symbol names and consumer/transport ABI headers stable as private native implementation identifiers. They are no_index and are not advertised as application classes; the public API is the IO/Kernel leaf surface. - Move repetitive Process stdout/stderr pipe draining into the native helper while preserving read_size, max_reads_per_tick, callback chunking, EOF order, and error behavior. Retain the gated process-pipe and ordered-byte performance regression coverage. - Rewrite README, module POD, architecture/design guides, framing/TLS/socket documentation, examples, MANIFEST, load contracts, and META provides for the new taxonomy. Rename Stream-, Wakeup-, and Datagram-centric design documents to ordered-byte, Event, and Dgram terminology and prevent the obsolete document names from returning through public-surface tests. - Keep all former top-level implementation packages out of META provides and mark them no_index. Public leaf POD now documents construction, callbacks, framing, flow control, deadlines, TLS, packet semantics, kernel ownership, and lifecycle directly rather than relying on internal implementation POD. 0.105 2026-08-29 - Add query-driven Loop introspection through running, count, has, objects, inspect, census, resources, why_alive, and pressure. Optional profile, stats, and reset_stats expose native timing and counters without adding permanent managed-object bookkeeping to the dispatch hot path. - Add explicit Stream callback batching. Raw subclasses may coalesce reads with read_batch_bytes, while framed subclasses may select bounded on_messages arrays with message_batch_size. Partial batches flush at the current read-drain boundary and never wait for future input. - Avoid inactive Stream deadline bookkeeping during read-interest and write-queue transitions. Focused watcher-state benchmarks retain Loop as the sole epoll owner and document why no cross-extension watcher ABI was introduced. - Split the Stream XS implementation into separately compiled state, transport, callback, input, delivery, read, write, transition, and per-framer C units behind one private header and one unchanged extension. - Move Stream subclass declarations, option validation, callback resolution, and immutable descriptor caching into the private Linux::Event::Stream::_Descriptor module while retaining Stream.pm as the public connection-lifecycle implementation. - Keep the deliberately tiny deadline Timer type beside Stream lifecycle policy, avoiding a new public module or unnecessary implementation layer. - Make the Timer microbenchmark fall back from the high-resolution process CPU clock to Perl process times, and report CPU timing as unavailable instead of failing installation when neither clock advances. Record the selected clock source in benchmark JSON and cover the fallback path. - Report non-Linux platforms as OS unsupported during configuration so CPAN Testers classifies the intentionally Linux-only distribution as NA rather than UNKNOWN. Add regression coverage for the configuration guard. - Add GitHub Actions coverage for supported Perl versions, distribution construction, metadata, POD, and native source packaging; publish CI, license, Perl, CPAN, and Kwalitee badges and complete the async extension boundary documentation. Exclude MakeMaker backup files from generated source archives. 0.104 2026-08-28 - Make the performance-regression and Timer benchmark smoke tests portable to systems whose process CPU clock does not advance for extremely small workloads. The benchmarks still reject non-positive timing samples. - Publish complete META spec 2 repository, bugtracker, and public-module provider metadata, plus security and contribution policies. 0.103 2026-08-27 - Make raw Loop registration handles stable lifecycle tokens. Cancelled, replaced, and Loop-destroyed handles are now inert even after native watcher storage or file-descriptor numbers are reused, and retained Perl state is released as soon as dispatch safety permits. - Restore Loop driver state after callback exceptions, reject recursive driving of the same Loop, reject event-capacity changes during dispatch, let run_once ignore an old stop request, and correct idle run_for statistics. - Apply Stream's normal high/low-watermark contract to output queued before attachment or connection readiness, including pending-byte reporting and exactly one delayed on_drain notification after the transport is usable. - Set adopted Stream descriptors nonblocking and close-on-exec, install the native drain callback only when requested by the subclass, and make callback-driven close safe throughout readiness, transition, drain, EOF, and transport-error dispatch. - Close Process stdin after max_pending_stdin overflow before reporting the typed output_limit error, so an over-limit producer cannot continue feeding that pipe. - Release Wakeup owner state on cancellation and reject attachment of a terminal Wakeup. - Add regression coverage for registration reuse and dispatch recovery, Loop driver contracts, Stream pre-connect flow control, adopted descriptor flags, callback-close safety, Process stdin limits, Signal recovery, Wakeup lifecycle, and TLS protocol transitions with leftover input. - Remove private implementation layers without changing the public API: Listener now uses its XS implementation directly, Stream and Datagram share Linux::Event::_Resolver, and the tiny Stream deadline helper lives in Stream.pm. 0.102 2026-08-21 - Fix Linux::Event::Wakeup compilation on Perl builds without PERL_IMPLICIT_CONTEXT, including ordinary non-threaded Perl. Such builds now use the sole interpreter identity while threaded/multiplicity builds retain pointer-based interpreter ownership checks. - Add regression coverage for interpreter identity on both multiplicity and non-multiplicity Perl configurations. 0.101 2026-08-21 - Publish the completed API as a stable release and synchronize every bundled Perl and XS component at version 0.101. - Add Linux::Event::Wakeup, a subclass-defined eventfd boundary with coalesced Loop-thread callbacks, safe fork signalling, and per-ithread descriptor duplication that keeps callbacks and data owner-confined. - Add production Stream socket policy at class and construction time: local address/port binding, TCP_NODELAY, keepalive tuning, TCP_USER_TIMEOUT in seconds, send/receive buffers, SO_BINDTODEVICE, live getters/setters, and a cached configure_socket hook. - Apply Stream socket policy before outbound bind/connect and before accepted or adopted transport attachment; expose local addresses and report family/configuration failures as structured Error values. - Extend the private asynchronous resolver with SOCK_DGRAM requests while preserving its typed native completion queue and cancellation model. - Add Linux::Event::Datagram for connected and unconnected UDP and Unix datagrams, native recvmsg/sendto packet I/O, lazy peer Addresses, whole- packet queues, soft backpressure, hard byte/packet limits, truncation detection, socket policy, ownership, detach, and Unix-path cleanup. - Add Linux::Event::Process using posix_spawnp, pidfd_open, waitid(P_PIDFD), and pidfd_send_signal, with asynchronous pipe stdio, decoded exit status, replacement environments, cwd support, SIGPIPE-safe stdin, atomic close-on-exec pipes, child-side closure of caller stdio source descriptors, deterministic final output draining, and partial-failure cleanup. - Make native resource objects interpreter-owned and non-clonable except for Wakeup's deliberately restricted signalling handle; rebuild cached native class descriptors lazily in a child ithread and reject stale Wakeup handles round-tripped from a worker interpreter. - Complete API, lifecycle, failure, ownership, thread/fork, local-binding, Datagram, and Process regression tests, including callback-exception and descriptor-reuse safety cases. - Add focused Wakeup, Datagram, and Process examples and microbenchmarks; update architecture, lifecycle, transport, roadmap, and module POD around the completed public surface with concrete annotated examples. - Harden distribution configuration for Linux, required libc/OpenSSL capabilities, CPAN metadata, manifest coverage, and clean distribution testing. 0.100_030 2026-08-21 - Make TLS declarative Stream policy: use Linux::Event::TLS on a Stream subclass and let connect or Listener acceptance select the client or server handshake role automatically. - Default outbound TLS server_name, SNI, and hostname verification to the connect host while retaining an explicit override for different service identities and adopted handles. - Load and validate accepted TLS certificate and key policy during Listener construction and create fresh native server state for every connection. - Pass Listener data automatically to each accepted Stream and remove the cumbersome accepted_stream_options hook from the public design. - Expose negotiated ALPN, protocol, cipher, and native TLS statistics directly on Stream without requiring access to its internal provider. - Add declaration validation, inheritance, role, callback-order, metadata, and integrated client/server regression coverage; update all current Listener, Stream, connection, and transport documentation to one model. 0.100_029 2026-08-21 - Add optional Listener on_accept($listener, $stream) after Stream construction and Loop attachment, before plain Stream readiness or TLS handshake completion. - Contain on_accept exceptions by closing only the affected Stream, suppressing its pending on_ready, and delivering a nonfatal callback Error through the Listener's on_error policy. - Make Listener family reporting consistent with Address: family returns inet, inet6, unix, or unknown; family_number retains the native value; is_tcp and is_unix provide convenience predicates. - Replace undefined Listener documentation placeholders with complete TCP, Unix, and adopted-socket examples annotated as required, default, or optional. - Add plain and TLS callback-order coverage plus callback-failure cleanup and family-accessor regression tests. 0.100_028 2026-08-21 - Correct inbound acquisition ownership: remove the accidental MyStream->listen() proxy and make Linux::Event::Listener->new with an explicit stream_class the sole Listener construction API. - Move runtime Listener error policy off Stream classes. The base Listener remains fatal; applications may override on_error in a Listener subclass. - Add established Stream idle, read, and write inactivity deadlines with cached subclass defaults and per-connection constructor overrides. - Add constructor and runtime overall-operation deadlines through deadline, set_deadline(), clear_deadline(), and monotonic after/at forms. - Start established deadlines only after plain or TLS transport readiness, leaving resolver, connection, TLS handshake, and TLS shutdown deadline ownership unchanged. - Track successful read and write progress natively only for Streams that enable inactivity policy; ordinary Streams perform no activity clock reads in their I/O path. - Use at most one private Timer per deadline-enabled Stream, sharing the Loop's existing timerfd and native deadline heap without exposing the internal Timer object. - Deliver typed timeout errors with operation, duration, and absolute deadline context, then follow ordinary on_error/on_close cleanup. - Add plain, TLS, transition, pause/resume, EOF, queued-write, lifecycle, validation, and benchmark regression coverage. 0.100_027 2026-08-21 - Move hostname resolution off the reactor thread into a private XS resolver with two lazy native pthread workers per Loop. - Deliver copied getaddrinfo results through one eventfd watched by the ordinary raw Loop API; no public eventfd, post, or threaded-Perl API is introduced. - Interleave IPv6 and IPv4 candidates, stagger pending attempts by 250 ms, transfer the first successful socket, and deterministically close losers. - Make cancellation discard late completion safely, include DNS in the connection deadline, retain literal-address bypass, and document that processes must fork before starting resolver workers. - Add native delivery, cancellation, hostname connection, ordering, and resolver microbenchmark coverage. - Add subclass-defined Linux::Event::Signal with one lazy signalfd and native fan-out registry per Loop, supporting several signals per object and several objects per signal. - Aggregate complete signalfd drains before callback delivery, preserve attachment-order fan-out, and make self/cross-cancellation callback-safe. - Track signal-mask ownership exactly, reject cross-Loop consumption of one signal number, restore only Loop-owned entries, and make resolver workers block signals independently. - Add Signal API, delivery, lifecycle, mask, error, and benchmark coverage plus explicit thread and fork ownership documentation. 0.100_026 2026-08-21 - Add Linux::Event::Timer as an abstract subclass-defined public object with cached on_timer callbacks and the same Loop->add attachment contract as Stream and Listener. - Support relative, absolute monotonic, and fixed-rate recurring schedules, including distinct first deadlines, in-callback rescheduling, and idempotent terminal cancellation. - Give each Loop one lazy timerfd and one indexed native minimum heap for every active Timer, with FIFO equal-deadline order and nanosecond internal deadlines. - Coalesce missed recurring ticks, retain fixed-rate phase, bound callback batches for descriptor fairness, and defer zero-delay callbacks to a later Loop turn. - Define deterministic ownership and cleanup: Loop retains active Timers; final expiration, cancellation, and Loop destruction release application data safely, including cancellation during a callback. - Extend statistics, lifecycle/API/scheduling tests, the release regression contract, and a dedicated scaling benchmark for Timer lifecycle, rescheduling, and expiration delivery. 0.100_025 2026-08-21 - Simplify the public hierarchy to Linux::Event::Loop, Stream, Listener, TLS, Framer, Error, and Address. Remove the public Watcher, IO, Connect, Connector, Listen, XSLoop, and XSWatcher compatibility modules. - Make MyStream->connect() the sole public outbound acquisition API and retain one Stream identity across connection, optional TLS readiness, established I/O, and close. Keep the acquisition engine private. - Make MyStream->listen() the normal inbound API and keep accept mechanics in a private Listener engine. Accepted descriptors become the configured Stream subclass directly, without a temporary public registration. - Support both loop => $loop construction and detached construction plus Loop->add() for Stream and Listener. Both forms attach the same object; add() sets its Loop and returns it. - Return only an opaque native registration from the low-level watch API; raw registrations are not a named public class hierarchy. - Consolidate errors under Linux::Event::Error, peer addresses under Linux::Event::Address, and native framing declarations under Linux::Event::Framer::*. - Rewrite the module POD, README, lifecycle, connection, Listener, core, architecture, and benchmark documentation around the reduced API. - Replace obsolete Connect/Listen benchmark modes with raw baselines and direct comparisons of loop => and Loop->add() attachment styles. - Add a permanent capture/compare performance-regression suite covering reactor registration, Stream lifecycle and throughput, native delimiter framing, and integrated connect/listen acquisition. - Align active XS source and build names with the reduced public model and remove stale XSLoop/XSWatcher terminology from the reactor source. 0.100_024 2026-08-16 - Introduce Linux::Event::Watcher as the public lifecycle contract and Linux::Event::Loop as the canonical XS-first loop name. - Add Loop->add() for detached high-level Watchers while retaining watch() as the immediate raw-IO registration convenience. - Return Linux::Event::IO objects from raw watch/watch_fd registration; XSWatcher remains their compatibility native-method base. - Make Stream, Connect, and Listen Watchers with detached construction and temporary loop-constructor compatibility. - Add MyStream->connect(), preserving one Stream identity through outbound connection, optional verified TLS negotiation, established I/O, and terminal close. Writes before readiness use the bounded Stream queue. - Add MyStream->listen() and Linux::Event::Listener, which construct and attach accepted Stream subclasses without application socket plumbing. - Add the noun-named Connector and Listener error/peer public aliases while retaining Connect and Listen as advanced compatibility layers. - Expand lifecycle tests through automatic plain and TLS client/server paths, strict Watcher attachment, raw IO typing, and stable identity. - Harden the Connect lifecycle benchmark with balanced order, abortive teardown, configurable deadlines, correctness checks, and JSON output; add integrated Stream and automatic Listener comparison rows. 0.100_023 2026-08-16 - Split the Listen benchmark's previous manual-to-raw gap with a handoff row that constructs the same Perl filehandle and lazy Peer representation without invoking Listen control or subclass callback machinery. - Remove an avoidable array shift from Listen's accepted-batch traversal. - Use eight rotating repeats by default so all four benchmark modes occupy every execution position equally. 0.100_022 2026-08-16 - Use equal abortive client teardown in every Listen benchmark mode so large matrices do not exhaust ephemeral ports through TIME_WAIT buildup. The complete default 540,000-connection matrix now runs without later rows failing from state accumulated by earlier rows. 0.100_021 2026-08-16 - Add a manual XSLoop/native-accept baseline to the permanent Listen lifecycle benchmark, separating Listen handoff cost from Stream cost. - Rotate benchmark mode order across repeats to reduce execution-order bias and print the tested Linux::Event version in the report. - Replace the overly aggressive hardcoded two-second connection deadline with a configurable --timeout option that defaults to 30 seconds. 0.100_020 2026-08-16 - Add Linux::Event::Listen as the inbound stream-socket acquisition layer. - Create TCP and Unix listeners or adopt an existing listening handle. - Drain accept4 in XS with atomic nonblocking and close-on-exec flags. - Add bounded level-triggered accept fairness and safe edge-trigger rules. - Add lazy peer addresses, typed failures, resource-error pause/recovery, ownership-aware close/detach behavior, and direct Stream handoff. - Add a runnable line-delimited echo server and permanent Listen lifecycle microbenchmark under the distribution examples and bench directories. - Recover from watched descriptor-number reuse by falling back from epoll MOD/ENOENT to ADD during same-fd watcher replacement. 0.100_019 2026-08-15 - Merge a redesigned Linux::Event::Connect into the main distribution. Concrete subclasses define cached on_connect and on_error methods while each request stores only target, lifecycle, and application data. - Transfer a generic connected nonblocking filehandle rather than requiring or constructing Linux::Event::Stream. Stream, TLS, raw watchers, and specialized protocol engines remain independent consumers. - Add typed Linux::Event::Connect::Error failures, a default 10-second connection deadline, silent idempotent cancellation, strict address-mode validation, and loop-dispatched callbacks for immediate outcomes. - Create sockets atomically with SOCK_NONBLOCK and SOCK_CLOEXEC. A small native timerfd helper supplies connection deadlines and deferred terminal delivery while candidate policy remains in the cold Perl control path. - Replace same-fd watchers through one EPOLL_CTL_MOD instead of DEL plus ADD. Old watcher handles remain inert, so Connect can hand a socket to Stream during on_connect and safely cancel only its original registration. - Retain synchronous getaddrinfo and sequential fallback as documented initial limitations. The public contract and internal attempt collection are prepared for a later asynchronous Resolver and Happy Eyeballs. 0.100_018 2026-08-15 - Prevent OpenSSL socket writes from delivering SIGPIPE when a TLS peer closes abruptly. The TLS extension now uses a non-owning custom socket BIO whose writes use Linux MSG_NOSIGNAL. - Preserve application signal policy: TLS does not install a process-wide SIGPIPE handler or add per-operation signal-mask syscalls. 0.100_017 2026-08-15 - Merge Linux::Event::TLS into the Linux-Event distribution so the reactor, Stream, and OpenSSL transport build and test with one top-level command. - Keep TLS in its own native extension and preserve Stream's specialized plain fast path; plain operations still make no OpenSSL calls. - Remove the duplicate transport ABI header and build the TLS provider against the canonical header owned by XSStream. - Move TLS integration, deadline, EOF, and certificate fixtures into the main test suite and simplify the TLS microbenchmark to use one blib tree. - Add an OpenSSL 1.1.1 configuration probe with a direct diagnostic for missing development headers or libraries. 0.100_016 2026-08-15 - Add generic cold-path transport lifecycle hooks used by adjacent providers to install, disarm, reuse, and destroy deadline watchers. - Preserve Stream/XSLoop layering: the core still knows no OpenSSL policy, while transport timeout failures use the existing typed error lifecycle. - Keep ordinary plain Streams free of auxiliary watchers and provider-hook calls in their read/write syscall paths. - Add the permanent top-level run-tls-microbench.pl same-Stream comparison for specialized plain and adjacent OpenSSL transports. 0.100_015 2026-08-15 - Publish transport => $provider construction for established descriptors through an exact-version native Stream transport ABI. - Retain provider lifetime in XS and coordinate cross-direction readiness for nonblocking handshakes, reads, writes, and transport shutdown. - Add transport(), is_transport_ready(), and the optional cached on_transport_ready callback while preserving the specialized plain path. - Reject detach() for non-plain transports because an encrypted descriptor cannot safely be returned as an application plaintext handle. - Support the adjacent Linux::Event::TLS OpenSSL provider without adding an OpenSSL dependency to the Linux-Event distribution. 0.100_014 2026-08-15 - Introduce an internal native transport operation contract beneath Stream buffering, framing, backpressure, and lifecycle semantics. - Route read, write, writev queue draining, retry classification, errors, EOF, and writable shutdown through the connection's transport provider. - Keep the ordinary plain-fd provider on a specialized direct-syscall path with no Perl callback or indirect function call per syscall. - Distinguish WANT_READ and WANT_WRITE in the native result contract for a future nonblocking OpenSSL provider. - Add transport_name(), plain-provider contract tests, regression benchmark coverage, and a detailed TLS/provider/STARTTLS boundary specification. 0.100_013 2026-08-14 - Add the optional class-level max_pending_bytes safety limit while keeping the existing high/low-watermark write() return contract unchanged. - Enforce the bound in XS before allocating an unsent queue segment, so the native pending-output queue never grows beyond its configured limit. - Report overflow as a typed output_limit Stream error with attempted pending_bytes and limit details, invoke on_error, and close the Stream. - Reject protocol transitions atomically when existing queued output exceeds the target class's nonzero max_pending_bytes policy. - Add deterministic output-limit tests, native overflow instrumentation, documentation, and capped/uncapped Stream transport benchmark rows. 0.100_012 2026-08-14 - Add in-place Stream protocol transitions through transition_to(). A live connection may change to another Stream subclass without replacing its filehandle, watcher, XSState, output queue, lifecycle, or application data. - Preserve unread native input across raw/framed protocol boundaries and accept an explicit raw-callback suffix through input => $bytes. - Stop the old native parser immediately after an input callback changes descriptors, then reinterpret remaining bytes with the new descriptor without waiting for another readiness event. - Make transition validation atomic, including target max_buffer checks, and retain pause, EOF, backpressure, queued-output, and instrumentation state. - Add transition contract tests, native transition counters, a dedicated transition benchmark, benchmark smoke coverage, and protocol-upgrade docs. 0.100_011 2026-08-14 - Redesign Linux::Event::Stream as a subclass-defined API. Callbacks, framing, and transport policy are class behavior; constructor state is limited to loop, fh, and optional per-connection data. - Resolve callbacks and framer/transport configuration once per concrete subclass into a shared immutable XS descriptor, with independent mutable parser and queue state for every connection. - Replace the framer factory and per-connection framer objects with declarative `use Linux::Event::Stream::Framer 'Name', @args` syntax. Exact package-name resolution removes the duplicate keyword registry. - Remove the arbitrary custom-framer object contract and Linux::Event::Stream::Framer::Buffer. Application-specific protocols now parse raw on_data bytes; generally useful families remain native built-ins. - Add cached class-level stream_options for read size, watermarks, and framed-buffer limits. - Rewrite Stream/framer tests, benchmarks, POD, guides, architecture notes, metadata, and examples for the canonical subclass-descriptor model. 0.100_010 2026-08-14 - Add the versioned Stream lifecycle and retained-memory benchmark used to capture the object-configured contract-1 baseline before the API redesign. 0.100_009 2026-08-13 - Add native inbound ASCII DecimalLength framing for wire forms such as RFC 6587 octet-counted syslog: "5 HELLO". - Support one configurable non-digit separator, include_prefix, max_frame, shared definitions, Perl fallback, and Perl outbound frame()/send(). - Reject invalid, overlong, overflowing, and non-canonical decimal lengths. - Extend native-framer tests, benchmarks, and the framer-selection guide. 0.100_008 2026-08-13 - Add canonical unsigned LEB128 Varint framing with native inbound parsing. - Preserve Perl outbound frame() compatibility and the custom-framer fallback. - Reject overflowing, overlong, and non-canonical Varint prefixes. - Extend native-framer benchmarks and simplify the framer-selection guide. 0.100_007 2026-08-13 - Add named Loop watch(fh => ...) and watch(fd => ...) construction. - Add Linux::Event::Stream::Framer factory methods for built-in framers. - Document and test safe reuse of built-in framer definitions across Streams. - Keep watch_fd and concrete Framer::* constructors available for low-level and subclass use. 0.100_006 2026-08-13 - Merge Linux::Event::Stream into the main Linux::Event distribution. - Build Linux::Event::XSLoop and Linux::Event::Stream native extensions from one source distribution and one top-level build/test/install workflow. - Keep the raw reactor and high-level Stream APIs as separate namespaces. - Unify development package versions for the merged native ABI snapshot. - Add a novice-oriented framer-selection guide in Markdown and POD. - Preserve native Delimiter, Fixed, LengthPrefix, U32BE, and Netstring framing plus the custom native-backed Buffer plug-in path. - Preserve the reactor, Stream, framing, and native-framer benchmark tools.