File Coverage

blib/lib/subs/parallel.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package subs::parallel;
2            
3 2     2   38605 use warnings;
  2         5  
  2         64  
4 2     2   11 use strict;
  2         3  
  2         42  
5            
6 2     2   39114 use threads;
  0            
  0            
7             use vars qw/@ISA @EXPORT $AUTOLOAD/;
8             use Attribute::Handlers;
9             use Scalar::Util qw/set_prototype/;
10            
11             =head1 NAME
12            
13             subs::parallel - enables subroutines to seamlessly run in parallel
14            
15             =head1 VERSION
16            
17             Version 0.09
18            
19             =cut
20            
21             require Exporter;
22             @ISA = qw(Exporter);
23             @EXPORT = qw(parallelize parallelize_sub parallelize_coderef);
24            
25             our $VERSION = '0.09';
26            
27             use overload
28             '""' => \&_deref,
29             '0+' => \&_deref,
30             'bool'=> \&_deref,
31             '${}' => \&_deref,
32             '@{}' => \&_deref,
33             '%{}' => \&_deref,
34             '&{}' => \&_deref,
35             '*{}' => \&_deref,
36             fallback => 1;
37            
38             =head1 SYNOPSIS
39            
40             use subs::parallel;
41            
42             sub foo : Parallel {
43             # foo runs in parallel
44             }
45            
46             parallelize_sub('bar');
47             # subroutine named bar now runs in parallel
48            
49             my $foo = foo(); # returns immediately
50             my $bar = bar(); # also returns immediately
51            
52             # now it might block waiting for both to finish
53             if ($foo == $bar) {
54             ...
55             }
56            
57            
58             my $baz = parallelize { ... code ... }; # returns immediately
59            
60             ...
61            
62             print "baz: $baz\n"; # if it's still running, blocks until it finishes
63            
64            
65             # it can be done to anonymous subs or any other coderefs too
66             my $anon = sub { ... more code ... };
67             my $parallel_coderef = parallelize_coderef($anon);
68            
69             my $foobar = $parallel_coderef->('arg'); # returns immediately
70            
71             ...
72            
73             # sub should return an object, no problem
74             $foobar->do_something_else(); # blocks until it finishes running
75            
76             =head1 DESCRIPTION
77            
78             This module gives Perl programmers the ability to easily and conveniently
79             create multi-threaded applications through B.
80            
81             Parallel subroutines are just plain old subroutines which happen to run in
82             another thread. When called, they return immediately to the calling thread but
83             keep running in another. When its return value is needed somewhere, the
84             returned value is transparently fetched. If the thread is still running, the
85             code blocks waiting for it to finish (since the program can't go on without a
86             value and keep being transparent).
87            
88             So, as it's possible to notice, the module interface aims to be as simple
89             as possible. In fact, it works in such a way that, aside from the
90             I directives, you wouldn't be able to tell it's a multi-threaded
91             application. All the thread handling (which isn't I complicated, really)
92             is done automagically.
93            
94             It should work for anything that's thread safe - even for subroutines whose
95             return values are not usually available across thread boundaries (for example,
96             usually, you can't C an object, but this module makes it possible to
97             return them without any problems, provided they're thread safe).
98            
99             =head1 MOTIVATION
100            
101             The main reason behind this module was the fact that Perl threads are not
102             widely used. Some could argue that this might happen because Perl threads are
103             not very practical to use. Others could say that the restrictions imposed by
104             the use of threads (you can't pass arbitrary data structures between threads).
105            
106             The latter issue is out of my reach. But, through the use of already existing
107             features, it was possible to mask it a little bit. So you can return anything
108             from your parallelized subroutines, but this is just some maybe unknown feature
109             of Cjoin>.
110            
111             The first issue is the main aim of this module: provide an extremely simple way
112             to make multi-threaded applications. Along this near-future reality of a
113             majority of dual-core computers, multi-threading might become the factor that
114             distiguishes good from bad software.
115            
116             But I would be dishonest if I didn't note that some part of the effort was
117             driven by the will to prove it could be done in Perl.
118            
119             =head1 ATTRIBUTE HANDLING
120            
121             The most practical way of using this module's features is through attrubutes.
122             This snippet ilustrates how to do it:
123            
124             use subs::parallel;
125            
126             sub foobar : Parallel {
127             # do stuff
128             }
129            
130             That way, C is declared as a B. This should have
131             exactly the same effect as using the C below, but is cleaner
132             and more convenient.
133            
134             =head1 EXPORTS
135            
136             The C, C and C subroutines
137             are exported. If you have problems with that, you're free to:
138            
139             use subs::parallel ();
140            
141             =head1 FUNCTIONS
142            
143             All the three functions available work similarly, implementing the idea of
144             B as explained above. Nevertheless, here's a brief
145             explanation of each of them.
146            
147             =head2 parallelize { BLOCK }
148            
149             Starts running the specified block of code in parallel B.
150             The snippet below ilustrates this concept:
151            
152             use subs::parallel;
153            
154             my $foo = parallelize {
155             # do stuff here
156             };
157            
158             my $bar = parallelize {
159             # do even more stuff
160             };
161            
162             # now we wait for them to finish
163             print "$foo, $bar\n";
164            
165             =cut
166            
167             # parallelizes and runs a block of code / coderef
168             sub parallelize (&) { parallelize_coderef(shift)->() }
169            
170             =head2 parallelize_sub(STRING)
171            
172             Transforms the named subroutine into a B. After this
173             modification, every it's called, it will run inside another thread and return
174             immediately to the caller.
175            
176             The snippet below ilustrates this concept:
177            
178             use subs::parallel;
179            
180             sub blocking_stuff {
181             # do blocking stuff
182             }
183            
184             blocking_stuff(); # this blocks
185            
186             parallelize_sub('blocking_stuff');
187            
188             blocking_stuff();
189             # now it returns immediately and the return values are discarded
190            
191             Note that, you can I named subroutines inside other packages:
192            
193             parallelize_sub('Other::Package::function');
194            
195             =cut
196            
197             # parallelizing subroutines by name
198             sub parallelize_sub {
199             my ($sub) = @_;
200            
201             # only prepend caller package if it's fully qualified
202             # allows easy parallelizing of subroutines inside other packages
203             if ($sub !~ /::/) {
204             my ($caller) = caller();
205             $sub = join('::', $caller, $sub);
206             }
207            
208             # we don't want nasty warnings - but don't try this at home
209             no strict 'refs';
210             no warnings 'redefine';
211            
212             croak("can't parallelize non-existant subroutine") unless defined *{$sub}{CODE};
213            
214             # keeps the prototype
215             *$sub = &set_prototype(parallelize_coderef(\&$sub), prototype($sub));
216             }
217            
218             =head2 parallelize_coderef(CODEREF)
219            
220             Returns a parallelized version of the given CODEREF. This function is used
221             internally to implement the other two functions explained above.
222            
223             my $code = sub { ... }
224             my $parallel = parallelize_coderef($code);
225            
226             my $return = $parallel->(@args); # runs in another thread
227            
228             =cut
229            
230             # returns a new coderef: a parallelized version of the original coderef
231             # the original is *not* modified
232             sub parallelize_coderef {
233             my ($coderef) = @_;
234            
235             return sub {
236             # this is the simple trick which makes this module work
237             my $scalar = threads->create($coderef, @_);
238             bless {thread => $scalar, caller => threads->tid}, __PACKAGE__;
239             };
240             }
241            
242             # support for parallelizing through subroutine attributes
243             sub UNIVERSAL::Parallel : ATTR(CODE) {
244             # for completeness sake, let's have the whole prototype
245             my ($caller, $symtable, $coderef, $attr, $data, $phase) = @_;
246            
247             no warnings 'redefine';
248             # keeps the prototype
249             *$symtable = &set_prototype(parallelize_coderef($coderef), prototype($coderef));
250             }
251            
252             # the overload handler
253             sub _deref {
254             my $class = CORE::ref $_[0];
255             # work-around in order to support scalar refs - yes, it's kinda ugly
256             # the alternative would be Acme::Damn but I feel kinda bad using Acme modules
257             bless $_[0], "${class}::NoOverload";
258             if (CORE::ref($_[0]->{thread}) eq 'threads') {
259             $_[0] = $_[0]->{thread}->join;
260             }
261             else {
262             # just in case - should never get here
263             croak(__PACKAGE__ . " object doesn't reference a threads object - something really bad happened");
264             }
265             return $_[0];
266             }
267            
268             # provide method calling support
269             sub AUTOLOAD {
270             # make errors appear to come from the caller
271             local $SIG{__DIE__} = sub { goto &croak };
272             (my $sub = $AUTOLOAD) =~ s/.*:://;
273             $_[0] = _deref($_[0]);
274             # unfortunately, if we used goto CODEREF, the call wouldn't be made as a
275             # method and warnings wouldn't be transparent. so, we prefer messing up the
276             # caller stack - which is not that used anyway, aside from instrospection
277             # modules.
278             shift->$sub(@_);
279             }
280            
281             sub croak {
282             # somehow, local $SIG handlers are not actually locally scoped
283             # this makes sure we get other possibly fatal errors
284             local $SIG{__DIE__} = '';
285             (my $err = shift) =~ s/ at [^ ]+ line (?:\d+).?\n//;
286             require Carp;
287             Carp::croak($err);
288             }
289            
290             # magic destructor!
291             # ok, ok... it just detaches the thread if we go out of scope.
292             # BUT ONLY IF we're the original caller of the thread
293             # this is a work-around for a strange behaviour of the perl threads implementation
294             sub DESTROY {
295             my $class = CORE::ref($_[0]);
296             bless $_[0], "${class}::NoOverload";
297             if (CORE::ref($_[0]->{thread}) eq 'threads' && $_[0]->{caller} == threads->tid) {
298             $_[0]->{thread}->detach;
299             }
300             }
301            
302             # provide overriden ref() function
303             sub ref ($) {
304             return CORE::ref($_[0]) if CORE::ref($_[0]) ne __PACKAGE__;
305             return CORE::ref($_[0]->_deref);
306             }
307             *CORE::GLOBAL::ref = \&ref;
308            
309             1;
310            
311             # ok, i didn't tie anything. oh well, can't use them all...
312            
313             =head1 INTERACTION WITH OTHER MODULES
314            
315             The only B issue is between this module and L. When using
316             L the C attribute seems to be broken. This is probably due
317             to L trying to process every possible attribute, but I'm not really
318             sure. Patches are welcome.
319            
320             There's a simple workaround. Instead of writing:
321            
322             sub foo : Parallel {
323             # code here
324             }
325            
326             Use the slightly more verbose:
327            
328             sub foo {
329             # code here
330             }
331            
332             parallelize_sub('foo');
333            
334             That should work in all cases.
335            
336             =head1 CAVEATS
337            
338             Currently, the parallel subroutines will always be called in scalar context.
339             There are plans for changing this in the future but, for now, if multiple
340             return values are needed, consider wrapping them around an array ref (this
341             feature would require adding the Want module as a dependency).
342            
343             In order for objects to survice across threads, both the calling and the
344             executing thread must have its class properly included. This means that you
345             can't require a module only inside a subroutine and then return an object
346             blessed into that class to the calling thread.
347            
348             You shouldn't pass to another thread/parallelized subroutines previous return
349             values from other parallelized subroutines without reading their values. And,
350             while you can get away with it, it's probably too much rope to hang yourself on
351             when things start to get ugly. This might be changed in the future, but would
352             require some sort of explicit synchronization through shared variables.
353            
354             Also, there's no way to tell if a parallelized subroutine is still running or
355             not. This probably will be changed in the future but, unfortunately, will
356             require either a minimalistic approach using some simple shared variables or
357             the use of Thread::Running, which would be another dependency and ends up using
358             shared variables anyway.
359            
360             The caller stack may behave in a non expected manner. When calling returned
361             object's methods, there will be an extra level in the stack, representing
362             C magic - the third form of C couldn't be used since that way
363             if the user called a non-existant method, he wouldn't get the default warning.
364             In the future, maybe this will be configurable so that if you need to rely on
365             the caller stack, you can make this trade-off.
366            
367             If the I subroutine dies, you won't get any warnings on notices
368             of any kind. It would be like it returned C. This might change in the
369             future.
370            
371             C is overriden. This may be an issue if there are other
372             modules in use which override it too. In the future, there may be a switch to
373             disable this.
374            
375             =head1 BUGS
376            
377             Besides the CAVEATS (which some people might consider to be bugs) there are no
378             known bugs.
379            
380             Please report any bugs or feature requests to
381             C, or through the web interface at
382             L.
383             I will be notified, and then you'll automatically be notified of progress on
384             your bug as I make changes.
385            
386             =head1 AUTHOR
387            
388             Nilson Santos F. Jr., C<< >>
389            
390             =head1 COPYRIGHT & LICENSE
391            
392             Copyright (C) 2005-2015 Nilson Santos Figueiredo Junior.
393            
394             This program is free software; you can redistribute it and/or modify it
395             under the same terms as Perl itself.
396            
397             =head1 SEE ALSO
398            
399             L
400            
401             =cut
402            
403             1; # End of subs::parallel