FCGI-EV-Std

 view release on metacpan or  search on metacpan

lib/FCGI/EV/Std/Nonblock.pm  view on Meta::CPAN

package FCGI::EV::Std::Nonblock;
use 5.010001;
use warnings;
use strict;
use utf8;
use Carp;

our $VERSION = 'v2.0.1';

use Scalar::Util qw( weaken refaddr );

use FCGI::EV::Std;
$FCGI::EV::Std::BLOCKING= 0;
$FCGI::EV::Std::MAIN    = \&new;
$FCGI::EV::Std::HUP     = \&HUP;

my $CB_START            = \&main::START;
my $CB_PRE              = \&main::PRE;
my $CB_POST             = \&main::POST;
my $CB_ERROR            = \&main::ERROR;
#my $HUP                 = undef;

my (%Active, %Server);


sub new {
    my ($server) = @_;
    my $self = bless {}, __PACKAGE__;
    $Active{ refaddr($self)     } = $server;
    $Server{ refaddr($server)   } = $self;
    weaken( $Active{ refaddr($self) } );
    $self->_wrapper($CB_START);
    return;
}

sub done {
    my ($self) = @_;
    if (exists $Active{ refaddr($self) }) {
        my $server = delete $Active{ refaddr($self) };
        if ($server) {
            delete $Server{ refaddr($server) };
            $server->stdout(q{}, 1);
        }
    }
    else {
        croak 'this request already done()';
    }
    return;
}

sub HUP {
    my ($server) = @_;
    return if !$server; # may happens during global destruction
    if (exists $Server{ refaddr($server) }) {
        my $self = delete $Server{ refaddr($server) };
#        $HUP && $HUP->($self);
    }
    return;
}

sub send {  ## no critic (ProhibitBuiltinHomonyms)
    my ($self, $buf) = @_;
    my $server = $Active{ refaddr($self) };
    if ($server) {
        $server->stdout($buf, 0);
    }
    return;
}

sub wrap_cb {
    my ($self, $cb, @p) = @_;
    weaken(my $this = $self);
    return sub { $this && $this->_wrapper($cb, @p, @_) };
}

sub _wrapper {
    my ($this, $cb, @p) = @_;

    $CB_PRE->($this);
    my $err = eval { $cb->($this, @p); 1 } ? undef : $@;
    $CB_POST->($this);

    if (defined $err) {
        $CB_ERROR->($this, $err);
    }
    return;
}


1; # Magic true value required at end of module
__END__

=encoding utf8

=for stopwords PRE

=head1 NAME

FCGI::EV::Std::Nonblock - Ease non-blocking CGI using FCGI::EV::Std


=head1 VERSION

This document describes FCGI::EV::Std::Nonblock version v2.0.1


=head1 SYNOPSIS

 use FCGI::EV;
 use FCGI::EV::Std;
 use FCGI::EV::Std::Nonblock;   # just loading module will activate it!

 FCGI::EV->new($sock, 'FCGI::EV::Std');

 #
 # Example CGI with FCGI::EV::Std::Nonblock interface
 #
 
 sub PRE {}
 sub POST {}
 sub ERROR {}
 sub START {
    my ($this) = @_;
    $this->{timer} = EV::timer 1, 0, $this->wrap_cb(\&reply);
 }

 sub reply {
    my ($this) = @_;
    $this->send("Status: 200 OK\r\n");
    $this->send("Content-Type: text/plain\r\n\r\n");
    $this->send("Reply after 1 sec!");
    $this->done();



( run in 0.636 second using v1.01-cache-2.11-cpan-63c85eba8c4 )