File Coverage

blib/lib/Promises/Deferred/AE.pm
Criterion Covered Total %
statement 28 32 87.5
branch 6 8 75.0
condition 2 3 66.6
subroutine 6 8 75.0
pod n/a
total 42 51 82.3


line stmt bran cond sub pod time code
1             package Promises::Deferred::AE;
2             our $AUTHORITY = 'cpan:YANICK';
3             # ABSTRACT: An implementation of Promises in Perl
4             $Promises::Deferred::AE::VERSION = '1.05';
5 2     2   3104 use strict;
  2         27  
  2         90  
6 2     2   11 use warnings;
  2         6  
  2         124  
7              
8 2     2   567 use AE;
  2         89  
  2         76  
9              
10 2     2   449 use parent 'Promises::Deferred';
  2         367  
  2         15  
11              
12             # Before the pipe-based approach used below, there was an AE::postpone-based
13             # approach for _notify_backend. The current code is much more performant:
14              
15             # Original code (on a laptop on battery power):
16             # Backend: Promises::Deferred::AE
17             # Benchmark: running one, two for at least 10 CPU seconds...
18             # one: 44 wallclock secs @ 3083.99/s (n=31210)
19             # two: 29 wallclock secs @ 1723.66/s (n=17340)
20              
21             # New approach:
22             # Backend: Promises::Deferred::AE
23             # Benchmark: running one, two for at least 10 CPU seconds...
24             # one: 11 wallclock secs @ 10457.90/s (n=108553)
25             # two: 11 wallclock secs @ 3878.69/s (n=40959)
26              
27              
28             my ($socket_pid, $socket_send, $socket_recv, $socket_io,
29             $read_buf, @io_callbacks);
30              
31             sub _do_callbacks {
32 84     84   4762 my @cbs = @io_callbacks;
33 84         163 @io_callbacks = ();
34 84         500 sysread $socket_recv, $read_buf, 16;
35 84         178 for my $cb_grp (@cbs) {
36 87         193 my ($result, $cbs) = @$cb_grp;
37 87         193 my @r = @$result;
38 87         277 $_->(@r) for @$cbs;
39             }
40             }
41              
42             sub _notify_backend {
43 88 100 66 88   654 if (! $socket_pid || $socket_pid != $$) {
44 2         28 $socket_pid = $$;
45 2 50       8 close($socket_send) if defined $socket_send;
46 2 50       8 close($socket_recv) if defined $socket_recv;
47 2         159 pipe($socket_recv, $socket_send);
48 2         80 $socket_io = AE::io($socket_recv, 0, \&_do_callbacks);
49             }
50              
51             # skip signalling when there are callbacks already waiting
52 88 100       6270 if (not @io_callbacks) {
53 85         581 syswrite $socket_send, ' ';
54             }
55 88         291 push @io_callbacks, [ $_[2], $_[1] ];
56             }
57              
58             sub _timeout {
59 0     0     my ( $self, $timeout, $callback ) = @_;
60              
61 0           my $id = AE::timer $timeout, 0, $callback;
62            
63 0     0     return sub { undef $id };
  0            
64             }
65              
66             1;
67              
68             __END__