NAME

Linux::Event::IO::TTY - asynchronous ordered-byte I/O for terminals and PTYs

SYNOPSIS

use v5.36;
use Linux::Event::Loop;
use Linux::Event::IO::TTY;

package Console;
use parent 'Linux::Event::IO::TTY';
use Linux::Event::Framer 'Delimiter', "\n";

package main;
my $loop = Linux::Event::Loop->new;
my $console = Console->new(
    loop     => $loop,
    read_fh  => \*STDIN,
    write_fh => \*STDOUT,
    on_message => sub ($tty, $line) {
        $tty->write("You typed: $line\n");
    },
);
$loop->run;

DESCRIPTION

Linux::Event::IO::TTY is the public ordered-byte I/O class for terminals and pseudo-terminals. It is appropriate for interactive standard input/output, PTY-backed subprocess interfaces, and other terminal handles that should use Linux::Event's native buffering and readiness machinery.

TTY owns asynchronous byte movement; it does not configure terminal modes, echo, canonical input, baud rates, or other termios policy. Applications that need those settings configure the terminal separately.

CALLBACKS, SUBCLASSING, AND TUNING

Constructor callbacks give each TTY ordinary lexical scope. A subclass is the right place for reusable terminal protocol policy: it can declare a native Linux::Event::Framer, define named callbacks, and centralize stream_options tuning. The Synopsis combines a delimiter-framing subclass with a per-object on_message closure.

stream_options controls read size and fairness, callback batching, buffer and output limits, watermarks, and established deadlines. Linux::Event validates and caches framer, tuning, and method policy once per subclass. Constructor callbacks override same-named methods for one TTY and are retained once per object; input delivery adds no repeated method lookup or method-versus-closure branch.

TLS does not apply to TTY; TLS transport policy is specific to Linux::Event::IO::Sock::Stream.

stream_options

Define stream_options as a class method on the TTY subclass. It returns key/value pairs, or one hash reference:

package InteractiveTTY;
use parent 'Linux::Event::IO::TTY';

sub stream_options ($class) {
    return (
        read_size        => 16_384,
        read_batch_bytes => 4_096,
        max_buffer       => 1_048_576,
    );
}

The complete option set is:

  • read_size (default 65,536)

    Maximum bytes requested by one native read; a positive integer.

  • read_budget_bytes (default 0)

    Maximum bytes read during one readiness drain. Zero drains until the input would block.

  • read_batch_bytes (default 0)

    For an unframed class, combine successful reads before on_data up to this non-negative byte target. A partial batch flushes when the current drain ends; zero preserves normal read callback boundaries. It is invalid on a framed class.

  • message_batch_size (default 0)

    For a framed class, deliver arrays of at most this many messages to on_messages. A partial batch flushes when the current drain ends; zero uses on_message. A positive value requires on_messages and is invalid on an unframed class.

  • max_buffer (default 8,388,608)

    Positive hard byte bound for retained input, an incomplete frame, and the aggregate payload retained for one message batch.

  • high_watermark (default 1,048,576)

    Non-negative pending-output byte level at which write or send begins returning false while still accepting the data.

  • low_watermark (default 262,144)

    Non-negative pending-output byte level at or below which on_drain fires after high-watermark backpressure. It must not exceed high_watermark.

  • max_pending_bytes (default 0)

    Hard non-negative pending-output byte limit. Zero means unbounded.

  • idle_timeout (default 0 seconds)

    Maximum inactivity interval since successful input or output progress. Zero disables it.

  • read_timeout (default 0 seconds)

    Maximum interval without inbound progress while reading is active. Pausing input suspends it; zero disables it.

  • write_timeout (default 0 seconds)

    Maximum interval without output progress while data is queued. Zero disables it.

Byte counts are integers. Timeout values are finite non-negative seconds and may be fractional. Constructor timeout values override class defaults for one TTY; the other values are class policy.

CONSTRUCTION

new accepts a shared fh, separate read_fh and write_fh, or either direction alone. Every supplied handle must be a TTY or PTY according to Perl's -t test. Separate input and output handles are intentionally supported, so STDIN and STDOUT can form one logical terminal object.

loop => $loop attaches immediately; detached objects may instead be passed to $loop->add($tty). data stores application state. Owned handles are made nonblocking and close-on-exec.

Established idle_timeout, read_timeout, write_timeout, and explicit deadline options use the common ordered-byte deadline model.

CALLBACKS AND FRAMING

A raw readable TTY requires on_data($tty, $bytes) as a method or constructor callback. A class that uses Linux::Event::Framer requires on_message($tty, $message) or, with explicit batching, on_messages($tty, $messages); either may be supplied by the class or constructor.

Delimiter framing is especially useful for line-oriented interactive input:

use Linux::Event::Framer 'Delimiter', "\n";

Framing operates on the bytes Linux supplies after the terminal's own line discipline. Linux::Event does not change canonical/raw terminal mode merely because a framer is declared.

Optional lifecycle callbacks are on_drain($tty), on_eof($tty), on_error($tty, $error), and on_close($tty).

The same callback names may be passed as coderefs to new. A constructor callback overrides the corresponding class method for that TTY and can capture normal Perl lexical state. Linux::Event resolves the effective callback once; it does not select between a method and closure for each input event.

OUTPUT AND LIFECYCLE

write submits raw bytes; send applies the declared framer. Native output queues preserve ordering and provide high/low-watermark backpressure.

pause_read and resume_read control application input. end drains the writable side, while close_read, close_write, and close provide immediate directional or whole-object termination.

detach transfers still-open directional handles to the caller when no output is queued. It is terminal and does not call on_close.

CLASS POLICY

stream_options configures the common ordered-byte engine. The complete option contract appears near the top of this document. Policy is cached per subclass so ordinary readiness does not parse options or look up callbacks.

SEE ALSO

Linux::Event::IO::Pipe, Linux::Event::IO::Sock::Stream, Linux::Event::Framer, docs/ORDERED-BYTE-IO-DESIGN.md.