Skip to content

Commit

Permalink
added Mojo::IOLoop::Steps
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Aug 16, 2012
1 parent f59fde2 commit eab886e
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 7 deletions.
4 changes: 3 additions & 1 deletion Changes
@@ -1,5 +1,7 @@

3.32 2012-08-16
3.32 2012-08-17
- Added Mojo::IOLoop::Steps.
- Added steps method to Mojo::IOLoop.
- Added tap method to Mojo::Base.
- Improved documentation.
- Fixed json_has method in Test::Mojo.
Expand Down
27 changes: 27 additions & 0 deletions lib/Mojo/IOLoop.pm
Expand Up @@ -5,6 +5,7 @@ use Carp 'croak';
use Mojo::IOLoop::Client;
use Mojo::IOLoop::Delay;
use Mojo::IOLoop::Server;
use Mojo::IOLoop::Steps;
use Mojo::IOLoop::Stream;
use Mojo::Reactor::Poll;
use Mojo::Util 'md5_sum';
Expand Down Expand Up @@ -156,6 +157,8 @@ sub start {
(ref $self ? $self : $self->singleton)->reactor->start;
}

sub steps { shift; Mojo::IOLoop::Steps->new(@_) }

sub stop {
my $self = shift;
(ref $self ? $self : $self->singleton)->reactor->stop;
Expand Down Expand Up @@ -540,6 +543,30 @@ reactors stop automatically if there are no events being watched anymore.
# Start event loop only if it is not running already
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
=head2 C<steps>
my $steps = Mojo::IOLoop->steps(sub {...}, sub {...});
my $steps = $loop->steps(sub {...}, sub {...});
Get L<Mojo::IOLoop::Steps> object to control the flow of events.
# Control the flow of multiple events
Mojo::IOLoop->steps(
sub {
my $steps = shift;
Mojo::IOLoop->timer(3 => $steps->next);
Mojo::IOLoop->timer(1 => $steps->next);
},
sub {
my ($steps, @args) = @_;
Mojo::IOLoop->timer(2 => $steps->next);
},
sub {
my ($steps, @args) = @_;
say "Thank you for waiting 5 seconds.";
}
);
=head2 C<stop>
Mojo::IOLoop->stop;
Expand Down
88 changes: 88 additions & 0 deletions lib/Mojo/IOLoop/Steps.pm
@@ -0,0 +1,88 @@
package Mojo::IOLoop::Steps;
use Mojo::Base -base;

sub new {
my $self = shift->SUPER::new(steps => [@_]);
$self->next->();
return $self;
}

# "My god, it's full of geezers."
sub next {
my $self = shift;
$self->{counter}++;
return sub { shift; $self->_step(@_) };
}

sub _step {
my $self = shift;

# Cache arguments
my $args = $self->{args} ||= [];
push @$args, @_;

# Next step
return unless --$self->{counter} <= 0;
return unless my $cb = shift @{$self->{steps}};
$self->{args} = [];
$self->$cb(@$args);
}

1;

=head1 NAME
Mojo::IOLoop::Steps - Control flow of events
=head1 SYNOPSIS
use Mojo::IOLoop::Steps;
# Control the flow of multiple events
my $steps = Mojo::IOLoop::Steps->new(
sub {
my $steps = shift;
Mojo::IOLoop->timer(3 => $steps->next);
Mojo::IOLoop->timer(1 => $steps->next);
},
sub {
my ($steps, @args) = @_;
Mojo::IOLoop->timer(2 => $steps->next);
},
sub {
my ($steps, @args) = @_;
say "Thank you for waiting 5 seconds.";
}
);
# Start event loop if necessary
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
=head1 DESCRIPTION
L<Mojo::IOLoop::Delay> controls the flow of events for L<Mojo::IOLoop>.
=head1 METHODS
L<Mojo::IOLoop::Steps> inherits all methods from L<Mojo::Base> and implements
the following new ones.
=head2 C<new>
my $steps = Mojo::IOLoop::Steps->new(sub {...}, sub {...});
Construct a new L<Mojo::IOLoop::Steps> object.
=head2 C<next>
my $cb = $steps->next;
Generate callback for getting to the next step. If more than one is generated,
they all have to be invoked before the next step can be reached. Note that the
first argument passed to the callback will be ignored.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
=cut
6 changes: 3 additions & 3 deletions lib/Mojolicious/Renderer.pm
Expand Up @@ -77,11 +77,11 @@ sub render {
handler => $stash->{handler},
template => delete $stash->{template}
};
my $data = $options->{data} = delete $stash->{data};
my $data = delete $stash->{data};
my $format = $options->{format} = $stash->{format} || $self->default_format;
my $inline = $options->{inline} = delete $stash->{inline};
my $json = $options->{json} = delete $stash->{json};
my $text = $options->{test} = delete $stash->{text};
my $json = delete $stash->{json};
my $text = delete $stash->{text};
$options->{handler} //= $self->default_handler if defined $inline;

# Text
Expand Down
4 changes: 2 additions & 2 deletions lib/Mojolicious/Routes.pm
Expand Up @@ -11,7 +11,7 @@ use Scalar::Util 'weaken';
has base_classes => sub { [qw(Mojolicious::Controller Mojo)] };
has cache => sub { Mojo::Cache->new };
has [qw(conditions shortcuts)] => sub { {} };
has hidden => sub { [qw(attr has new)] };
has hidden => sub { [qw(attr has new tap)] };
has 'namespace';

sub add_condition {
Expand Down Expand Up @@ -300,7 +300,7 @@ Contains all available conditions.
$r = $r->hidden([qw(attr has new)]);
Controller methods and attributes that are hidden from routes, defaults to
C<attr>, C<has> and C<new>.
C<attr>, C<has>, C<new> and C<tap>.
=head2 C<namespace>
Expand Down
2 changes: 1 addition & 1 deletion t/mojo/delay.t
Expand Up @@ -47,7 +47,7 @@ for my $i (3, 3) {
}
is $delay->wait, 3, 'right results';

# Mojo::IOLoop
# Event loop
$finished = undef;
$delay = Mojo::IOLoop->delay(sub { shift; $finished = [@_, 'too!'] });
for my $i (1, 1) {
Expand Down
64 changes: 64 additions & 0 deletions t/mojo/steps.t
@@ -0,0 +1,64 @@
use Mojo::Base -strict;

# Disable IPv6 and libev
BEGIN {
$ENV{MOJO_NO_IPV6} = 1;
$ENV{MOJO_REACTOR} = 'Mojo::Reactor::Poll';
}

use Test::More tests => 3;

# "It's not just safe, it's 40% safe!"
use Mojo::IOLoop;
use Mojo::IOLoop::Steps;

# Basic functionality
my $result;
my $steps = Mojo::IOLoop::Steps->new(
sub {
my $steps = shift;
$steps->next->(1, 2, 3);
},
sub {
my ($steps, @numbers) = @_;
$result = \@numbers;
}
);
is_deeply $result, [2, 3], 'right numbers';

# Multiple steps
$result = undef;
$steps = Mojo::IOLoop::Steps->new(
sub {
my $steps = shift;
my $cb = $steps->next;
$steps->next->(1, 2, 3);
$cb->(3, 2, 1);
},
sub { shift->next->(@_) },
sub {
my ($steps, @numbers) = @_;
$result = \@numbers;
}
);
is_deeply $result, [2, 3, 2, 1], 'right numbers';

# Event loop
$result = undef;
$steps = Mojo::IOLoop->steps(
sub {
my $steps = shift;
my $delay = Mojo::IOLoop->delay;
$delay->on(finish => $steps->next);
Mojo::IOLoop->timer(0 => $delay->begin);
Mojo::IOLoop->timer(0 => $steps->next);
$delay->begin;
Mojo::IOLoop->timer(0 => sub { $delay->end(1, 2, 3) });
},
sub {
my ($steps, @numbers) = @_;
$result = \@numbers;
}
);
Mojo::IOLoop->start;
is_deeply $result, [1, 2, 3], 'right numbers';

0 comments on commit eab886e

Please sign in to comment.