Revision history for Linux-Event

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.
