multithreading - Passing subroutine references to perl threads -
i trying pass subroutine references perl threads implement threadmap subroutine. in environment have 'roll own' of things; installing new perl packages not option.
also, running perl version 5.10. in work environment, versions of perl > 5.10 not available.
i can pass subroutine references around without trouble. however, once try pass subroutine reference thread, thread not appear understand it.
here proposed threadmap subroutine, comments are, believe, sufficiently explanatory interested question-answerers.
#input: hash keys l (listref), f (function can apply each element of l), , optionally nthreads #default nthreads 50 #divides l sublists each thread, kicks off threads #each thread applies f each element of sublist #and returns result of $f on each item #output: map{ &$f($_) } @{$l}, done threadily sub threadmap{ %arg = @_; ($l,$f,$nthr) = ($arg{l},$arg{f},$arg{nthreads}); $maxthreads = 50; if(not defined $nthr or $nthr > $maxthreads){ $nthr = $maxthreads; } &log(1,"threadmap: have f $f"); @threadlists = &makesublistsforthreads($l,$nthr); #in event l less $nthr, reduce number of threads $nthr = scalar(@threadlists); @threads; @ret; for(0 .. $nthr-1){ #invoke threads in list context # push @threads, threads->create({'context' => 'list'}, sub{ ($l,$f) = @_; print "i have l <@$l> , f $f\n"; return (map{ &f($_) } @{$l}) }, ($threadlists[$_],$f) ); push @threads, threads->create({'context' => 'list'}, sub{ ($l) = @_; print "i have l <@$l> , f $f\n"; return (map{ &f($_) } @{$l}) }, ($threadlists[$_]) ); } for(@threads){ #each thread returns items, them in order push @ret, $_->join(); } return @ret; }
when run script called 'foo' has approximately following:
my @l = (1 .. 5); $f = sub{ ($i) = @_; return 100*$i; }; print "i have f $f\n"; @out = &threadmap("l"=>\@l,"f"=>$f); &log(1,"i had input <@l> , output <@out>"); @realout = map{ &$f($_) } @l; &log(1,"output should <@realout>");
i output:
i have f code(0xbf3530)
wed jul 17 10:27:49 2013: threadmap: have f code(0xbf3530)
i have l <1> , f code(0x110f100)
thread 1 terminated abnormally: undefined subroutine &main::f called @ /u/jamie /perl/jdperllib.pl line 6037.
i have l <2> , f code(0x16b3df0)
thread 2 terminated abnormally: undefined subroutine &main::f called @ /u/jamie /perl/jdperllib.pl line 6037.
i have l <3> , f code(0x1a7d7b0)
thread 3 terminated abnormally: undefined subroutine &main::f called @ /u/jamie/perl/jdperllib.pl line 6037.
i have l <4> , f code(0x1fbb600)
thread 4 terminated abnormally: undefined subroutine &main::f called @ /u/jamie/perl/jdperllib.pl line 6037.
i have l <5> , f code(0x7fd5240b78c0)
thread 5 terminated abnormally: undefined subroutine &main::f called @ /u/jamie/perl/jdperllib.pl line 6037.
wed jul 17 10:27:49 2013: had input <1 2 3 4 5> , output <>
this tells me function reference constant foo top of threadmap subroutine, once passed threads gets changed , goes haywire. why this? can avoid it?
note fails both
#invoke threads in list context # push @threads, threads->create({'context' => 'list'}, sub{ ($l,$f) = @_; print "i have l <@$l> , f $f\n"; return (map{ &f($_) } @{$l}) }, ($threadlists[$_],$f) ); push @threads, threads->create({'context' => 'list'}, sub{ ($l) = @_; print "i have l <@$l> , f $f\n"; return (map{ &f($_) } @{$l}) }, ($threadlists[$_]) );
and
#invoke threads in list context push @threads, threads->create({'context' => 'list'}, sub{ ($l,$f) = @_; print "i have l <@$l> , f $f\n"; return (map{ &f($_) } @{$l}) }, ($threadlists[$_],$f) ); #push @threads, threads->create({'context' => 'list'}, sub{ ($l) = @_; print "i have l <@$l> , f $f\n"; return (map{ &f($_) } @{$l}) }, ($threadlists[$_]) );
also, first post stackoverflow, question clear enough, or too/insufficiently verbose?
you calling function named "f" inside threadmap:
map{ &f($_) } ...
which function, error message indicates, not exist.
you mean dereference , invoke coderef instead:
map { $f->($_) } ...
in update comment, code works because there define sub named "f".
as aside, should not call perl subs ampersand sigil. hold-over syntax perl 4, , has specific semantics in perl 5 never needed when merely want call sub.
calling &f
disable prototype handling , can pass along @_
— if behavior doesn't seem useful you, don't use feature. &
used when denoting sub per se (e.g., my $coderef = \&f
or defined &f
) , special goto &f
invocations. &
dereferences code ref, typically invoke it, operation more conveyed arrow , parentheses: $coderef->()
.
Comments
Post a Comment