The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Reflex - Class library for flexible, reactive programs.

VERSION

version 0.071

SYNOPSIS

        # See eg-18-synopsis-no-moose.pl if you don't like Moose.
        # See eg-32-promise-tiny.pl if you prefer promises (condvar-like).
        # See eg-36-coderefs-tiny.pl if you prefer coderefs and/or closures.

        {
                package App;
                use Moose;
                extends 'Reflex::Base';
                use Reflex::Interval;

                has ticker => (
                        isa     => 'Reflex::Interval',
                        is      => 'rw',
                        setup   => { interval => 1, auto_repeat => 1 },
                        traits  => [ 'Reflex::Trait::Observed' ],
                );

                sub on_ticker_tick {
                        print "tick at ", scalar(localtime), "...\n";
                }
        }

        exit App->new()->run_all();

DESCRIPTION

Reflex is a library of classes that assist with writing reactive (AKA event-driven) programs. Reflex uses Moose internally, but it doesn't enforce programs to use Moose's syntax. However, Moose syntax brings several useful features we hope will become indispensible.

Reflex is considered "reactive" because it's an implementation of the reactor pattern. http://en.wikipedia.org/wiki/Reactor_pattern

About Reactive Objects

Reactive objects provide responses to interesting (to them) stimuli. For example, an object might be waiting for input from a client, a signal from an administrator, a particular time of day, and so on. The App object in the SYNOPSIS is waiting for timer ticks. It generates console messages in response to those timer ticks.

Example Reactive Objects

Here an Echoer class emits "pong" events in response to ping() commands. It uses Moose's extends(), but it could about as easily use warnings, strict, and base instead. Reflex::Base provides emit().

        package Echoer;
        use Moose;
        extends 'Reflex::Base';

        sub ping {
                my ($self, $args) = @_;
                print "Echoer was pinged!\n";
                $self->emit( event => "pong" );
        }

The next object uses Echoer. It creates an Echoer and pings it to get started. It also reacts to "pong" events by pinging the Echoer again. Reflex::Trait::Observed implicitly watches the object in echoer(), mapping its "pong" event to the on_echoer_pong() method.

        package Pinger;
        use Moose;
        extends 'Reflex::Base';

        has echoer => (
                is      => 'ro',
                isa     => 'Echoer',
                default => sub { Echoer->new() },
                traits  => ['Reflex::Trait::Observed'],
        );

        sub BUILD {
                my $self = shift;
                $self->echoer->ping();
        }

        sub on_echoer_pong {
                my $self = shift;
                print "Pinger got echoer's pong!\n";
                $self->echoer->ping();
        }

Then the Pinger would be created and run.

        Pinger->new()->run_all();

A complete, runnable version of this example is in the distribution as eg/eg-37-ping-pong.pl.

Coderef Callbacks

Reflex supports any conceivable callback type, even the simple ones: plain old coderefs. In other words, you don't need to write objects to handle events.

Here we'll start a periodic timer and handle its ticks with a simple callback. The program is still reactive. Every second it prints "timer ticked" in response Reflex::Interval's events.

        use Reflex::Interval;
        use ExampleHelpers qw(eg_say);
        use Reflex::Callbacks qw(cb_coderef);

        my $t = Reflex::Interval->new(
                interval    => 1,
                auto_repeat => 1,
                on_tick     => cb_coderef { eg_say("timer ticked") },
        );

        $t->run_all();

cb_coderef() is explicit placeholder syntax until a final syntax is decided upon.

A complete, runnable version of the above example is available as eg/eg-36-tiny-coderefs.pl in the distribution.

Promises Instead of Callbacks

Callback haters are not left out. Reflex objects may also be used as inline promises. The following example is identical in function to the previous coderef callback example, but it doesn't use callbacks at all.

It may not be obvious, but the same emit() method drives all of Reflex's forms of callback. Reflex::Interval below is identical to the Reflex::Interval used differently elsewhere.

        use Reflex::Interval;
        use ExampleHelpers qw(eg_say);

        my $t = Reflex::Interval->new(
                interval => 1,
                auto_repeat => 1,
        );

        while (my $event = $t->next()) {
                eg_say("next() returned an event (@$event)");
        }

PUBLIC METHODS

Reflex itself contains some convenience methods for cleaner semantics.

run_all

Run all active Reflex objects until they destruct.

        # (omitted: create some Reflex objects)

        Reflex->run_all();
        exit;

BUNDLED MODULES AND DOCUMENTATION INDEX

Reflex bundles a number of helpful base classes to get things started.

Core Modules

The basic modules upon which most everything else is built.

Reflex - Class library for flexible, reactive programs.
Reflex::Base - Base class for reactive (aka, event driven) objects.
Reflex::Role::Reactive - Make an object reactive (aka, event driven).

Callback Adapters

Reflex provides adapters for nearly every kind of callback that exists, including condvar-like promises that allow Reflex objects to be used inline without callbacks at all.

Reflex::Callback - Generic callback adapters to simplify calling back
Reflex::Callback::CodeRef - Callback adapter for plain code references
Reflex::Callback::Method - Callback adapter for class and object
Reflex::Callback::Promise - Non-callback, inline Promise adapter
Reflex::Callbacks - Convenience functions for creating and using

POE Adapters

POE provides over 400 modules for various useful things. Reflex can work with them using these adapters.

Reflex::POE::Event - Communicate with POE components expecting events.
Reflex::POE::Postback - Communicate with POE components expecting
Reflex::POE::Session - Observe events from a POE::Session object.
Reflex::POE::Wheel - Base class for POE::Wheel wrappers.
Reflex::POE::Wheel::Run - Represent POE::Wheel::Run as a Reflex class.

Object Collections

It's often useful to manage collections of like-typed modules, such as connections or jobs.

Reflex::Role::Collectible - add manageability by Reflex::Collection
Reflex::Collection - Autmatically manage a collection of collectible

I/O

Event driven programs most often react to I/O of some sort. These modules provide reactive I/O support.

Reflex::Acceptor - non-blocking client socket acceptor
Reflex::Client - A non-blocking socket client.
Reflex::Connector - non-blocking client socket connector
Reflex::Role::Accepting - add connection accepting to a class
Reflex::Role::Connecting - add non-blocking client connecting to a class
Reflex::Role::Readable - add readable-watching behavior to a class
Reflex::Role::Recving - Mix standard send/recv code into a class.
Reflex::Role::Streaming - add streaming I/O behavior to a class
Reflex::Role::Writable - add writable-watching behavior to a class
Reflex::Stream - Buffered, translated I/O on non-blocking handles.
Reflex::UdpPeer - Base class for non-blocking UDP networking peers.

Signals and Child Processes

Modules that provide signal support, including SIGCHLD for child process management.

Reflex::PID - Observe the exit of a subprocess by its SIGCHLD signal.
Reflex::Signal - Generic signal watcher and base class for specific

Timers

Timer management has been relatively overlooked so far. We'll get to it eventually, and you're welcome to help.

Reflex::Interval - An object that emits periodic events.

Breadboarding Traits

Reflex also implements signal/slot style object interaction, through emit() and watch() methods. These traits were inspired by Smalltalk's observable object attributes.

Reflex::Trait::EmitsOnChange - Emit an event when an attribute’s value
Reflex::Trait::Observed - Automatically watch Reflex objects.

ASSISTANCE

Thank you for volunteering to assist with this project. You can find like-minded people in a few places, in descending order of preference. Or, oh, wait, maybe you wanted assistance using it? We'll help you, too. :)

See irc.perl.org #reflex for help with Reflex.

See irc.perl.org #poe for help with POE and Reflex.

See irc.perl.org #moose for help with Moose.

Support is officially available from POE's mailing list as well. Send a blank message to poe-subscribe@perl.org to join.

The Reflex package also has helpful examples which may serve as a tutorial until Reflex is documented more.

ACKNOWLEDGEMENTS

irc.perl.org channel #moose and #poe. The former for assisting in learning their fine libraries, sometimes against everyone's better judgement. The latter for putting up with lengthy and sometimes irrelevant design discussion for oh so long.

SEE ALSO

Moose, POE, the Reflex namespace on CPAN.

Ohlo - https://www.ohloh.net/p/reflex-perl

CIA - http://cia.vc/stats/project/reflex

TODO - Set up home page.

BUGS

We appreciate your feedback, bug reports, feature requests, patches and kudos. You may enter them into our request tracker by following the instructions at https://rt.cpan.org/Dist/Display.html?&Queue=Reflex.

We also accept e-mail at bug-Reflex@rt.cpan.org.

AUTHORS

Rocco Caputo, RCAPUTO on CPAN.

CONTRIBUTORS

Reflex is open source, and we welcome involvement.

Chris Fedde, CFEDDE on CPAN

TODO

Please browse the source for the TODO marker. Some are visible in the documentation, and others are sprinlked around in the code's comments.

Also see "TODO.otl" in docs in the distribution. This is a Vim Outliner file with the current roadmap and progress.

Set up Dist::Zilla to reduce technical debt and make releasing code fun again.

COPYRIGHT AND LICENSE

Copyright 2009-2010 by Rocco Caputo.

Reflex is free software. You may redistribute and/or modify it under the same terms as Perl itself.

TODO - Use the latest recommended best practice for licenses.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 343:

Non-ASCII character seen before =encoding in 'attribute’s'. Assuming UTF-8