The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package Gearman::Server::Listener;

use strict;
use base 'Danga::Socket';
use fields qw(server accept_per_loop);

use Errno qw(EAGAIN);
use Socket qw(IPPROTO_TCP TCP_NODELAY SOL_SOCKET SO_ERROR);

sub new {
    my Gearman::Server::Listener $self = shift;
    my $sock = shift;
    my $server = shift;

    my %opts = @_;

    my $accept_per_loop = delete $opts{accept_per_loop};

    warn "Extra options passed into new: " . join(', ', keys %opts) . "\n"
        if keys %opts;

    $accept_per_loop = 10 unless defined $accept_per_loop and $accept_per_loop >= 1;

    $self = fields::new($self) unless ref $self;

    # make sure provided listening socket is non-blocking
    IO::Handle::blocking($sock, 0);

    $self->SUPER::new($sock);

    $self->{server} = $server;
    $self->{accept_per_loop} = int($accept_per_loop);

    $self->watch_read(1);

    return $self;
}

sub event_read {
    my Gearman::Server::Listener $self = shift;

    my $listen_sock = $self->sock;

    local $!;
    local $SIG{PIPE} = "IGNORE";

    my $remaining = $self->{accept_per_loop};

    while (my $csock = $listen_sock->accept) {
        IO::Handle::blocking($csock, 0);
        setsockopt($csock, IPPROTO_TCP, TCP_NODELAY, pack("l", 1)) or die;

        my $server = $self->{server};

        $server->debug(sprintf("Listen child making a Client for %d.", fileno($csock)));
        $server->new_client($csock);
        return unless $remaining-- > 0;
    }

    return if $! == EAGAIN;

    warn "Error accepting incoming connection: $!\n";

    $self->watch_read(0);

    Danga::Socket->AddTimer( .1, sub {
        $self->watch_read(1);
    });
}

1;