File Coverage

blib/lib/Object/Remote/Future.pm
Criterion Covered Total %
statement 63 80 78.7
branch 13 18 72.2
condition 7 12 58.3
subroutine 14 20 70.0
pod 0 3 0.0
total 97 133 72.9


line stmt bran cond sub pod time code
1             package Object::Remote::Future;
2              
3 15     15   97 use strict;
  15         30  
  15         598  
4 15     15   129 use warnings;
  15         25  
  15         824  
5 15     15   82 use base qw(Exporter);
  15         23  
  15         2165  
6              
7 15     15   99 use Object::Remote::Logging qw( :log router );
  15         28  
  15         107  
8              
9 15     15   71 BEGIN { router()->exclude_forwarding }
10              
11 15     15   9840 use Future;
  15         230909  
  15         16087  
12              
13             our @EXPORT = qw(future await_future await_all);
14              
15             sub future (&;$) {
16 136     136 0 1357 my $f = $_[0]->(Future->new);
17 136 100 50     2580 return $f if ((caller(1+($_[1]||0))||'') eq 'start');
18 110         478 await_future($f);
19             }
20              
21             our @await;
22              
23             sub await_future {
24 175     175 0 1315 my $f = shift;
25 175     0   1761 log_trace { my $ir = $f->is_ready; "await_future() invoked; is_ready: $ir" };
  0         0  
  0         0  
26 175 50       3415 return $f if $f->is_ready;
27 175         2571 require Object::Remote;
28 175         1407 my $loop = Object::Remote->current_loop;
29             {
30 175         390 local @await = (@await, $f);
  175         801  
31             $f->on_ready(sub {
32 175     175   5328 log_trace { my $l = @await; "future has become ready, length of \@await: '$l'" };
  0         0  
  0         0  
33 175 50       3338 if ($f == $await[-1]) {
34 175         1189 log_trace { "This future is not waiting on anything so calling stop on the run loop" };
  0         0  
35 175         9378 $loop->stop;
36             }
37 175         1808 });
38 175     0   6124 log_trace { "Starting run loop for newly created future" };
  0         0  
39 175         3355 $loop->run;
40             }
41 175 100 66     1127 if (@await and $await[-1]->is_ready) {
42 57     0   802 log_trace { "Last future in await list was ready, stopping run loop" };
  0         0  
43 57         1837 $loop->stop;
44             }
45 175     0   1406 log_trace { "await_future() returning" };
  0         0  
46 175 100       7476 return wantarray ? $f->get : ($f->get)[0];
47             }
48              
49             sub await_all {
50 0     0 0 0 log_trace { my $l = @_; "await_all() invoked with '$l' futures to wait on" };
  0     2   0  
  2         543  
51 2         90 await_future(Future->wait_all(@_));
52 2         63 map $_->get, @_;
53             }
54              
55             package start;
56              
57             our $start = sub { my ($obj, $call) = (shift, shift); $obj->$call(@_); };
58              
59             sub AUTOLOAD {
60 13     13   254012 my $invocant = shift;
61 13         103 my ($method) = our $AUTOLOAD =~ /^start::(.+)$/;
62 13         25 my $res;
63 13 50       27 unless (eval { $res = $invocant->$method(@_); 1 }) {
  13         150  
  13         125  
64 0         0 my $f = Future->new;
65 0         0 $f->fail($@);
66 0         0 return $f;
67             }
68 13 100 100     141 unless (Scalar::Util::blessed($res) and $res->isa('Future')) {
69 2         16 my $f = Future->new;
70 2         30 $f->done($res);
71 2         120 return $f;
72             }
73 11         49 return $res;
74             }
75              
76             package maybe;
77              
78             sub start {
79 0     0   0 my ($obj, $call) = (shift, shift);
80 0 0 0     0 if ((caller(1)||'') eq 'start') {
81 0         0 $obj->$start::start($call => @_);
82             } else {
83 0         0 $obj->$call(@_);
84             }
85             }
86              
87             package maybe::start;
88              
89             sub AUTOLOAD {
90 48     48   1617 my $invocant = shift;
91 48         348 my ($method) = our $AUTOLOAD =~ /^maybe::start::(.+)$/;
92 48 100 50     356 $method = "start::${method}" if ((caller(1)||'') eq 'start');
93 48         808 $invocant->$method(@_);
94             }
95              
96             package then;
97              
98             sub AUTOLOAD {
99 2     2   5 my $invocant = shift;
100 2         14 my ($method) = our $AUTOLOAD =~ /^then::(.+)$/;
101 2         5 my @args = @_;
102             return $invocant->then(sub {
103 2     2   827 my ($obj) = @_;
104 2         6 return $obj->${\"start::${method}"}(@args);
  2         19  
105 2         21 });
106             }
107              
108             1;
109              
110             =head1 NAME
111              
112             Object::Remote::Future - Asynchronous calling for L
113              
114             =head1 LAME
115              
116             Shipping prioritised over writing this part up. Blame mst.
117              
118             =cut