NAME

Acme::Parataxis::Driver::Mojo - Mojo::IOLoop and Mojo::Reactor Driver for Parataxis

SYNOPSIS

use v5.40;
use Acme::Parataxis qw[await_read await_sleep fiber];
use Mojo::IOLoop;

# Attach Mojo's loop:
Acme::Parataxis->attach_loop( Mojo::IOLoop->new );

Acme::Parataxis::run( sub {
    my $ponger = fiber {
        await_sleep(30);
        syswrite( $socket, "ping\n" );
    };

    await_read( $socket, 2000 );
} );

Acme::Parataxis->detach_loop;

# Or drive a bare Mojo::Reactor directly:
Acme::Parataxis->attach_loop( $ioloop->reactor );

DESCRIPTION

Acme::Parataxis::Driver::Mojo connects Parataxis to Mojolicious event loops. It allows fibers executing await_read, await_write, and await_sleep to be driven directly by a Mojo::IOLoop or Mojo::Reactor.

Key implementation details:

  • Single I/O watcher constraint: Mojo reactors support exactly one io() watcher callback per filehandle. Directional interest is updated via $reactor->watch($fh, $read, $write). The driver manages this automatically, allowing fibers to watch reading and writing concurrently on a single descriptor while sharing a single reactor slot.

  • Handle non-blocking persistence: The driver sets filehandles non-blocking via $fh->blocking(0) when first registered and leaves them non-blocking. Code sharing handles with this driver must expect non-blocking behavior.

  • Reactor duck-typing: Accepts a full Mojo::IOLoop or any object implementing the Mojo::Reactor interface (such as an embedded worker reactor).

CONSTRUCTOR

new( loop => $loop_or_reactor )

my $driver = Acme::Parataxis::Driver::Mojo->new( loop => $loop );

Constructs a new driver instance. Accepts a Mojo::IOLoop or any reactor providing a one_tick() method.

METHODS

watch_read( $fh, $cb ) / watch_write( $fh, $cb )

Registers interest in read or write readiness on $fh, installing the reactor io() callback if not already present and updating the interest mask. Returns $fh. Croaks if $fh is closed.

unwatch( $fh )

Removes all I/O registrations for $fh from the reactor. Returns true if the handle was monitored; false otherwise.

timer( $ms, $cb )

Arms a reactor timer for $ms milliseconds. Returns an opaque timer ID.

cancel_timer( $id )

Cancels an active timer via $reactor->remove($id). Returns true if cancelled; false if already fired or unknown.

drive( )

Executes $reactor->one_tick. Runs one iteration of the reactor (waiting for I/O or the earliest timer).

poll_ready( )

Also executes $reactor->one_tick. See "Behavior Notes" regarding Mojo polling characteristics.

Behavior Notes

  • one_tick always waits for the earliest timer

    Mojo's one_tick() method does not take a timeout argument; it always waits until an event occurs or the earliest registered timer fires. Because of this, poll_ready() and drive() execute the identical call. If long timers are armed, polling passes will wait out that duration before returning.

  • Reactor shutdown on idle tick

    Calling one_tick on a reactor with no active I/O watchers and no timers stops the reactor. Parataxis only calls drive() while $driver->pending is positive, avoiding this condition.

SEE ALSO

Acme::Parataxis, Acme::Parataxis::Driver, Acme::Parataxis::Driver::IOAsync, Mojo::IOLoop

AUTHOR

Sanko Robinson https://github.com/sanko

LICENSE

Copyright (C) Sanko Robinson.

This library is free software; you can redistribute it and/or modify it under the terms found in the Artistic License 2.