Acme-Parataxis

 view release on metacpan or  search on metacpan

lib/Acme/Parataxis.pod  view on Meta::CPAN

            my $f2 = Acme::Parataxis->spawn(
                sub {
                    say '  Task 2: Performing I/O...';

                    # await_read/write for non-blocking socket handling
                    return 'I/O Done';
                }
            );

            # Block current fiber until results are ready (without blocking the thread)
            say 'Result 1: ' . $f1->await( );
            say 'Result 2: ' . $f2->await( );
        }
    );

Or do things the more modern way:

    use v5.40;
    use Acme::Parataxis qw[:all];
    $|++;

    async {
        say 'Main task started';

        # 'fiber' is a shorter alias for 'spawn'
        my $f1 = fiber {
            say '  Task 1: Sleeping...';
            await_sleep(1000);
            return 42;
        };

        my $f2 = fiber {
            say '  Task 2: Performing I/O...';
            # ...
            return 'I/O Done';
        };

        # 'await' works on fibers and futures
        say 'Result 1: ' . await($f1);
        say 'Result 2: ' . await($f2);
    };

=head1 DESCRIPTION

C<Acme::Parataxis> implements a hybrid concurrency model for Perl, greatly inspired by the concurrency system for the
L<Wren|https://wren.io/concurrency.html> programming language. It combines cooperative multitasking (fibers) with a
preemptive native thread pool.

Fibers are a mechanism for lightweight concurrency. They are similar to threads but are cooperatively scheduled. While
the OS may switch between threads at any time, a fiber only passes control when explicitly told to do so. This makes
concurrency deterministic and easier to reason about. You (probably) don't have to worry about random context switches
clobbering your data.

Fibers are incredibly lightweight. Each one has its own stack and context, but they don't use OS thread resources. You
can easily create thousands of them without stalling your system.

=head2 A Warning

I had this idea while writing cookbook examples for Affix. I wondered if I could implement a hybrid concurrency model
for Perl from within FFI. This is that unpublished article made into a module. It's fragile. It's dangerous. It's my
attempt at combining cooperative multitasking (green threads or fibers or whatever they're called in the latest edit of
Wikipedia) with a preemptive native thread pool. It's Acme::Parataxis.

This module is experimental and resides in the C<Acme::> namespace for a reason. It manually manipulates Perl's
internal stacks and C context. It is very dangerous. It's irresponsible, honestly, that I'm even putting this terrible
idea into the world. Don't use this. Forget you even saw it. Just B<reading> this has probably made your projects more
prone to breaking. Reading the package name out loud might cause brain damage to yourself and those within earshot.

Close the browser and clear your history before this does further harm!

=head1 MODERN API

While the classic object-oriented API is always available, C<Acme::Parataxis> exports a set of functions (via the
C<:all> tag) that provide a more modern, concise way to write concurrent code.

=head2 C<async { ... }>

A convenience wrapper around C<run( )>. It starts the scheduler, executes the provided block as the main fiber, and
automatically calls C<stop( )> when the block completes.

    async {
        say "The scheduler is running!";
    };

=head2 C<fiber { ... }>

An alias for C<spawn( )>. It creates a new fiber and returns a L<Future|/"Acme::Parataxis::Future OBJECT METHODS">.

    my $f = fiber {
        say "Hello from fiber!";
    };

=head2 C<await( $thing )>

A generic await function. It accepts either an C<Acme::Parataxis> fiber object or an C<Acme::Parataxis::Future> and
suspends the current fiber until the target is ready.

    my $result = await($f);

=head2 C<await_sleep( $ms )>

Suspends the current fiber for C<$ms> milliseconds. This is a non-blocking operation that allows other fibers to run
while the current one is paused.

    async {
        say "Taking a nap...";
        await_sleep(1000);
        say "I'm awake!";
    };

=head2 C<await_read( $fh, $timeout = 5000 )>

Suspends the current fiber until the provided filehandle is ready for reading, or the timeout is reached.

    async {
        await_read($socket);
        my $data = <$socket>;
        say "Received: $data";
    };

=head2 C<await_write( $fh, $timeout = 5000 )>



( run in 0.397 second using v1.01-cache-2.11-cpan-13bb782fe5a )