about summary refs log tree commit homepage
path: root/lib/PublicInbox/HTTPD
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2019-12-25 07:50:42 +0000
committerEric Wong <e@80x24.org>2019-12-26 10:48:19 +0000
commitb7fbffd1f8c125566b944e37a21ab0747728bdc1 (patch)
treefe3df94adca570b8d3b0b386c5af0d731761d58e /lib/PublicInbox/HTTPD
parent2131a3cd0a1cad6f7d6a2c6439676f9f2a039ff7 (diff)
downloadpublic-inbox-b7fbffd1f8c125566b944e37a21ab0747728bdc1.tar.gz
Cheaper to use up two hash table slots than creating a new sub.
Diffstat (limited to 'lib/PublicInbox/HTTPD')
-rw-r--r--lib/PublicInbox/HTTPD/Async.pm42
1 files changed, 20 insertions, 22 deletions
diff --git a/lib/PublicInbox/HTTPD/Async.pm b/lib/PublicInbox/HTTPD/Async.pm
index 8956f719..f4de2719 100644
--- a/lib/PublicInbox/HTTPD/Async.pm
+++ b/lib/PublicInbox/HTTPD/Async.pm
@@ -10,7 +10,7 @@ package PublicInbox::HTTPD::Async;
 use strict;
 use warnings;
 use base qw(PublicInbox::DS);
-use fields qw(cb arg end_obj);
+use fields qw(http fh cb arg end_obj);
 use Errno qw(EAGAIN);
 use PublicInbox::Syscall qw(EPOLLIN EPOLLET);
 
@@ -31,21 +31,24 @@ sub new {
         my $self = fields::new($class);
         IO::Handle::blocking($io, 0);
         $self->SUPER::new($io, EPOLLIN | EPOLLET);
-        $self->{cb} = $cb; # initial read callback, later replaced by main_cb
+        $self->{cb} = $cb; # initial read callback
         $self->{arg} = $arg; # arg for $cb
         $self->{end_obj} = $end_obj; # like END{}, can ->event_step
         $self;
 }
 
-sub main_cb ($$) {
-        my ($http, $fh) = @_;
-        sub {
-                my ($self) = @_;
+sub event_step {
+        my ($self) = @_;
+        if (my $cb = delete $self->{cb}) {
+                # this may call async_pass when headers are done
+                $cb->(delete $self->{arg});
+        } elsif (my $sock = $self->{sock}) {
+                my $http = $self->{http};
                 # $self->{sock} is a read pipe for git-http-backend or cgit
                 # and 65536 is the default Linux pipe size
-                my $r = sysread($self->{sock}, my $buf, 65536);
+                my $r = sysread($sock, my $buf, 65536);
                 if ($r) {
-                        $fh->write($buf); # may call $http->close
+                        $self->{fh}->write($buf); # may call $http->close
                         if ($http->{sock}) { # !closed
                                 $self->requeue;
                                 # let other clients get some work done, too
@@ -57,11 +60,11 @@ sub main_cb ($$) {
                         return; # EPOLLET means we'll be notified
                 }
 
-                # Done! Error handling will happen in $fh->close
-                # called by the {end} handler
+                # Done! Error handling will happen in $self->{fh}->close
+                # called by end_obj->event_step handler
                 delete $http->{forward};
-                $self->close; # queues ->{end} to be called
-        }
+                $self->close; # queues end_obj->event_step to be called
+        } # else { # we may've been requeued but closed by $http
 }
 
 # once this is called, all data we read is passed to the
@@ -79,21 +82,16 @@ sub async_pass {
         # calls after this may use much memory:
         $$bref = undef;
 
-        # replace the header read callback with the main one
-        my $cb = $self->{cb} = main_cb($http, $fh);
-        $cb->($self); # either hit EAGAIN or ->requeue to keep EPOLLET happy
-}
+        $self->{http} = $http;
+        $self->{fh} = $fh;
 
-sub event_step {
-        # {cb} may be undef after ->requeue due to $http->close happening
-        my $cb = $_[0]->{cb} or return;
-        $cb->(@_);
+        # either hit EAGAIN or ->requeue to keep EPOLLET happy
+        event_step($self);
 }
 
-# may be called as $forward->close in PublicInbox::HTTP or EOF (main_cb)
+# may be called as $forward->close in PublicInbox::HTTP or EOF (event_step)
 sub close {
         my $self = $_[0];
-        delete $self->{cb};
         $self->SUPER::close; # DS::close
 
         # we defer this to the next timer loop since close is deferred