use EV;
use Socket ();
use POSIX ();
use Fcntl ();
use strict;
use 5.010;
$| = 1;

sub FASTLOOP_OPTIMIZED { 1 };
#sub FASTLOOP_OPTIMIZED { 0 };

my @w;

sub install_fastloop {
    if (FASTLOOP_OPTIMIZED()) {
        my $l = EV::Loop->new( EV::BACKEND_KQUEUE );
        push @w, EV::embed($l);
        return $l;
    }
    else {
        return EV::default_loop;
    }
}

$EV::DIED = sub {
    warn $!;
    exit;
};

push @w, EV::signal(
    'HUP',
    sub {
        say "HUP DECLARED BEFORE FORK ($$)";
    }
);

socketpair my $ch0, my $ch1, &Socket::AF_UNIX, &Socket::SOCK_STREAM, &Socket::PF_UNSPEC or die "socketpair: $!";
fcntl $ch0, &Fcntl::F_SETFL, &Fcntl::O_NONBLOCK;
fcntl $ch1, &Fcntl::F_SETFL, &Fcntl::O_NONBLOCK;

my $pid = fork;

if ($pid) {
    my $pp = "master";
    say "$pp pid $$";
    my $channel = $ch0;
    close( $ch1 );

    my $l = install_fastloop();

    push @w, $l->io(
        $channel, EV::READ,
        sub {
            my $data = readline($channel);
            chomp($data);
            say "$pp $data";
        }
    );

    push @w, EV::timer( 2, 0, sub {
        say "$pp send hello ($$)";
        syswrite $channel, "HELLO FROM MASTER\n";
    });

    push @w, EV::signal(
        'INT',
        sub {
            say "$pp got SIGINT ($$)";
            EV::unloop;
        }
    );

    EV::loop;
    kill &POSIX::SIGINT, $pid;
    waitpid( $pid, 0 );
    say "$pp END";
}
else {
    my $pp = "\tchild";
    say "$pp pid $$";
    close( $ch0 );
    my $channel = $ch1;
    EV::default_loop->loop_fork;

    my $l = install_fastloop();

    push @w, $l->io(
        $channel, EV::READ,
        sub {
            my $data = readline($channel);
            chomp($data);
            say "$pp $data";
        }
    );

    push @w, EV::timer( 3, 0, sub {
        say "$pp send hello ($$)";
        syswrite $channel, "HELLO FROM CHILD\n";
    });

    push @w, EV::signal(
        'INT',
        sub {
            say "$pp got SIGINT ($$)";
            EV::unloop;
        }
    );

    EV::loop;
    say "$pp END";
}

