While Perl implements tail recursion via `goto' which allows
avoiding warnings on deep recursion. It doesn't (as of 5.28)
optimize the speed of such dispatches, though it may reduce
ephemeral memory usage.
Make the code less alien to hackers coming from other languages
by using normal subroutine dispatch. It's actually slightly
faster in micro benchmarks due to the complexity of `goto &NAME'.
}
# reentrant SIGCHLD handler (since reap_pids is not reentrant)
}
# reentrant SIGCHLD handler (since reap_pids is not reentrant)
-sub enqueue_reap { $reap_armed //= requeue(\&reap_pids) }
+sub enqueue_reap () { $reap_armed //= requeue(\&reap_pids) }
sub in_loop () { $in_loop }
sub in_loop () { $in_loop }
push @$wait_pids, [ @_ ]; # [ $pid, $cb, $arg ]
# We could've just missed our SIGCHLD, cover it, here:
push @$wait_pids, [ @_ ]; # [ $pid, $cb, $arg ]
# We could've just missed our SIGCHLD, cover it, here:
- goto &enqueue_reap; # tail recursion
sub new_sub {
my (undef, $ref) = @_;
# special case for messages like <85k5su9k59.fsf_-_@lola.goethe.zz>
sub new_sub {
my (undef, $ref) = @_;
# special case for messages like <85k5su9k59.fsf_-_@lola.goethe.zz>
- $$ref =~ /\A(\r?\n)/s or goto &new;
+ $$ref =~ /\A(\r?\n)/s or return new(undef, $ref);
my $hdr = substr($$ref, 0, $+[0], ''); # sv_chop on $$ref
bless { hdr => \$hdr, crlf => $1, bdy => $ref }, __PACKAGE__;
}
my $hdr = substr($$ref, 0, $+[0], ''); # sv_chop on $$ref
bless { hdr => \$hdr, crlf => $1, bdy => $ref }, __PACKAGE__;
}
sub event_step {
my ($ctx, $sync) = @_;
# can't find a partial match in current inbox, try the others:
sub event_step {
my ($ctx, $sync) = @_;
# can't find a partial match in current inbox, try the others:
- my $ibx = shift @{$ctx->{again}} or goto \&finalize_partial;
+ my $ibx = shift @{$ctx->{again}} or return finalize_partial($ctx);
my $mids = search_partial($ibx, $ctx->{mid}) or
return ($sync ? undef : PublicInbox::DS::requeue($ctx));
$ctx->{n_partial} += scalar(@$mids);
push @{$ctx->{partial}}, [ $ibx, $mids ];
my $mids = search_partial($ibx, $ctx->{mid}) or
return ($sync ? undef : PublicInbox::DS::requeue($ctx));
$ctx->{n_partial} += scalar(@$mids);
push @{$ctx->{partial}}, [ $ibx, $mids ];
- $ctx->{n_partial} >= PARTIAL_MAX ? goto(\&finalize_partial)
+ $ctx->{n_partial} >= PARTIAL_MAX ? finalize_partial($ctx)
: ($sync ? undef : PublicInbox::DS::requeue($ctx));
}
: ($sync ? undef : PublicInbox::DS::requeue($ctx));
}
# synchronous fall-through
$ctx->event_step while @{$ctx->{again}};
}
# synchronous fall-through
$ctx->event_step while @{$ctx->{again}};
}
- goto \&finalize_partial;
+ finalize_partial($ctx);
- # my ($self, $want) = @_;
- push @{$_[0]->{todo}}, $_[1];
- goto \&next_step # retry solve_existing
+ my ($self, $want) = @_;
+ push @{$self->{todo}}, $want;
+ next_step($self); # retry solve_existing
my ($self, $want) = @_;
# do we have more inboxes to try?
my ($self, $want) = @_;
# do we have more inboxes to try?
- goto \&retry_current if scalar @{$want->{try_ibxs}};
+ return retry_current($self, $want) if scalar @{$want->{try_ibxs}};
my $cur_want = $want->{oid_b};
if (length($cur_want) > $OID_MIN) { # maybe a shorter OID will work
my $cur_want = $want->{oid_b};
if (length($cur_want) > $OID_MIN) { # maybe a shorter OID will work
chop($cur_want);
dbg($self, "retrying $want->{oid_b} as $cur_want");
$want->{oid_b} = $cur_want;
chop($cur_want);
dbg($self, "retrying $want->{oid_b} as $cur_want");
$want->{oid_b} = $cur_want;
- goto \&retry_current; # retry with shorter abbrev
+ return retry_current($self, $want); # retry with shorter abbrev
}
dbg($self, "could not find $cur_want");
}
dbg($self, "could not find $cur_want");
my $job = { oid_b => $src, path_b => $di->{path_a} };
push @{$self->{todo}}, $job;
}
my $job = { oid_b => $src, path_b => $di->{path_a} };
push @{$self->{todo}}, $job;
}
- goto \&next_step; # onto the next todo item
+ return next_step($self); # onto the next todo item
+ try_harder($self, $want);
}
sub extract_diff_async {
}
sub extract_diff_async {
PublicInbox::Eml->new($bref)->each_part(\&extract_diff, $x, 1);
}
PublicInbox::Eml->new($bref)->each_part(\&extract_diff, $x, 1);
}
- scalar(@{$want->{try_smsgs}}) ?
- retry_current($self, $want) :
- extract_diffs_done($self, $want);
+ scalar(@{$want->{try_smsgs}}) ? retry_current($self, $want)
+ : extract_diffs_done($self, $want);
}
sub resolve_patch ($$) {
}
sub resolve_patch ($$) {
- goto(scalar @$msgs ? \&retry_current : \&extract_diffs_done);
+ return scalar(@$msgs) ? retry_current($self, $want)
+ : extract_diffs_done($self, $want);
}
# see if we can find the blob in an existing git repo:
}
# see if we can find the blob in an existing git repo:
return;
}
mark_found($self, $cur_want, $existing);
return;
}
mark_found($self, $cur_want, $existing);
- goto \&next_step; # onto patch application
+ return next_step($self); # onto patch application
} elsif ($existing > 0) {
} elsif ($existing > 0) {
+ return retry_current($self, $want);
} else { # $existing == 0: we may retry if inbox scan (below) fails
delete $want->{try_gits};
}
} else { # $existing == 0: we may retry if inbox scan (below) fails
delete $want->{try_gits};
}
$want->{try_smsgs} = $msgs;
$want->{cur_ibx} = $ibx;
$self->{tmp_diffs} = [];
$want->{try_smsgs} = $msgs;
$want->{cur_ibx} = $ibx;
$self->{tmp_diffs} = [];
+ return retry_current($self, $want);
+ try_harder($self, $want);
}
# this API is designed to avoid creating self-referential structures;
}
# this API is designed to avoid creating self-referential structures;
# public, called by public-inbox-index
sub index_sync {
my ($self, $opt) = @_;
# public, called by public-inbox-index
sub index_sync {
my ($self, $opt) = @_;
- $opt //= $_[1] //= {};
- goto \&xapian_only if $opt->{xapian_only};
+ $opt //= {};
+ return xapian_only($self, $opt) if $opt->{xapian_only};
my $pr = $opt->{-progress};
my $epoch_max;
my $pr = $opt->{-progress};
my $epoch_max;
sub stream_thread_i { # PublicInbox::WwwStream::getline callback
my ($ctx, $eml) = @_;
sub stream_thread_i { # PublicInbox::WwwStream::getline callback
my ($ctx, $eml) = @_;
- goto &thread_eml_entry if $eml; # tail recursion
+ return thread_eml_entry($ctx, $eml) if $eml;
return unless exists($ctx->{skel});
my $ghost_ok = $ctx->{nr}++;
while (1) {
return unless exists($ctx->{skel});
my $ghost_ok = $ctx->{nr}++;
while (1) {
PublicInbox::Sigfd::sig_setmask($oldset);
die $@ if $@;
}
PublicInbox::Sigfd::sig_setmask($oldset);
die $@ if $@;
}
- goto(&fs_scan_step) if $self->{mdre};
+ fs_scan_step($self) if $self->{mdre};
}
sub watch_imap_fetch_all ($$) {
}
sub watch_imap_fetch_all ($$) {
sub scan {
my ($self, $op) = @_;
push @{$self->{ops}}, $op;
sub scan {
my ($self, $op) = @_;
push @{$self->{ops}}, $op;