File Coverage

blib/lib/EV/Future.pm
Criterion Covered Total %
statement 14 14 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 19 19 100.0


line stmt bran cond sub pod time code
1             package EV::Future;
2              
3 6     6   691152 use 5.010000;
  6         20  
4 6     6   25 use strict;
  6         33  
  6         148  
5 6     6   35 use warnings;
  6         8  
  6         417  
6              
7             our $VERSION = '0.03';
8              
9 6     6   1188 use EV ();
  6         5474  
  6         154  
10 6     6   31 use base 'Exporter';
  6         8  
  6         1462  
11             our @EXPORT = qw(parallel parallel_limit series);
12              
13             require XSLoader;
14             XSLoader::load('EV::Future', $VERSION);
15              
16             =head1 NAME
17              
18             EV::Future - Minimalist and high-performance async control flow for EV
19              
20             =head1 SYNOPSIS
21              
22             use EV;
23             use EV::Future;
24              
25             my @watchers;
26             parallel([
27             sub { my $done = shift; push @watchers, EV::timer 0.1, 0, sub { print "Task 1 done\n"; $done->() } },
28             sub { my $done = shift; push @watchers, EV::timer 0.2, 0, sub { print "Task 2 done\n"; $done->() } },
29             ], sub {
30             print "All parallel tasks finished\n";
31             });
32              
33             parallel_limit([
34             sub { my $done = shift; push @watchers, EV::timer 0.1, 0, sub { print "Task A\n"; $done->() } },
35             sub { my $done = shift; push @watchers, EV::timer 0.2, 0, sub { print "Task B\n"; $done->() } },
36             sub { my $done = shift; push @watchers, EV::timer 0.1, 0, sub { print "Task C\n"; $done->() } },
37             ], 2, sub {
38             print "All limited-parallel tasks finished\n";
39             });
40              
41             series([
42             sub { my $done = shift; print "Task 1 start\n"; $done->() },
43             sub { my $done = shift; print "Task 2 start\n"; $done->() },
44             ], sub {
45             print "All series tasks finished\n";
46             });
47              
48             EV::run;
49              
50             =head1 DESCRIPTION
51              
52             Focuses on performance and minimalism, offloading task management to XS.
53              
54             All three functions (C, C, C) are exported
55             by default.
56              
57             If C<\@tasks> is empty, C is called immediately. Non-coderef
58             elements in C<\@tasks> are treated as immediately-completed no-op tasks.
59              
60             =head2 TASKS
61              
62             Each task is a coderef that receives a single argument: a "done" callback.
63             The task MUST call this callback exactly once when it is finished.
64              
65             =head3 Exceptions
66              
67             In safe mode (the default), if a task throws an exception (e.g., via C),
68             the exception will be propagated immediately and internal memory is cleaned up
69             correctly. In unsafe mode, exceptions bypass cleanup and will leak memory.
70              
71             =head3 Double-calls
72              
73             Calling the C callback more than once for a single task is considered
74             incorrect usage. In safe mode (the default), C prevents
75             catastrophic failure:
76              
77             =over 4
78              
79             =item *
80              
81             In C and C, extra calls to a specific C
82             callback are silently ignored.
83              
84             =item *
85              
86             In C, extra calls to a specific C callback are ignored. Only
87             the C callback provided to the I task can advance the
88             series.
89              
90             =back
91              
92             In unsafe mode, these protections are B. Double-calls will
93             corrupt the internal completion counter, which may cause premature
94             invocation of C (before all tasks have actually completed).
95              
96             =head1 FUNCTIONS
97              
98             =head2 parallel(\@tasks, \&final_cb, [$unsafe])
99              
100             Executes all tasks concurrently. The C is called once all tasks
101             have invoked their C callback.
102              
103             If the optional C<$unsafe> flag is set to a true value, C will skip
104             evaluating tasks inside a C block and will reuse a single callback
105             object for all tasks. This provides a massive performance boost (up to 100%
106             faster) but bypasses per-task double-call protection and will cause issues
107             if tasks throw exceptions. Use only when performance is critical and tasks
108             are well-behaved.
109              
110             =head2 parallel_limit(\@tasks, $limit, \&final_cb, [$unsafe])
111              
112             Executes tasks concurrently, but with at most C<$limit> tasks in-flight at
113             any time. As each task completes, the next pending task is dispatched.
114              
115             C<$limit> is clamped to the range C<1..scalar(@tasks)>. With C<$limit E= @tasks>
116             this behaves like C; with C<$limit == 1> it runs tasks sequentially.
117              
118             There is no cancellation mechanism for C; all dispatched
119             tasks must complete.
120              
121             The C<$unsafe> flag has the same meaning as in C.
122              
123             =head2 series(\@tasks, \&final_cb, [$unsafe])
124              
125             Executes tasks one by one. The next task is only started after the current
126             task calls its C callback.
127              
128             If the optional C<$unsafe> flag is set to a true value, error-checking overhead
129             is bypassed for maximum performance. See C for warnings about exceptions.
130              
131             To cancel the series and skip all subsequent tasks (in both safe and
132             unsafe modes), pass a true value to the C callback:
133              
134             series([
135             sub { my $d = shift; $d->(1) }, # Cancel here
136             sub { die "This will never run" },
137             ], sub {
138             print "Series finished early\n";
139             });
140              
141             =head1 BENCHMARKS
142              
143             1000 synchronous tasks, 5000 iterations (C):
144              
145             --- PARALLEL (iterations/sec) ---
146             EV::Future (unsafe) 4,386
147             EV::Future (safe) 2,262
148             AnyEvent::cv (begin/end) 1,027
149             Future::XS::wait_all 982
150             Promise::XS::all 32
151              
152             --- PARALLEL LIMIT 10 (iterations/sec) ---
153             EV::Future (unsafe) 4,673
154             EV::Future (safe) 2,688
155             Future::Utils::fmap_void 431
156              
157             --- SERIES (iterations/sec) ---
158             EV::Future (unsafe) 5,000
159             AnyEvent::cv (stack-safe) 3,185
160             EV::Future (safe) 2,591
161             Future::XS (chain) 893
162             Promise::XS (chain) 809
163              
164             Safe mode allocates a per-task CV for double-call protection and wraps
165             each dispatch in C. Unsafe mode reuses a single shared CV and
166             skips C, roughly doubling throughput.
167              
168             =head1 SEE ALSO
169              
170             L, L, L
171              
172             =head1 AUTHOR
173              
174             vividsnow
175              
176             =head1 LICENSE
177              
178             This library is free software; you can redistribute it and/or modify
179             it under the same terms as Perl itself.
180              
181             =cut
182              
183             1;