我正在尝试将子例程引用传递给 perl 线程以实现 threadMap 子例程。我所处的环境中,大多数事情我都必须“自己动手”;安装新的 perl 包不是一种选择。
另外,我正在运行 perl 5.10 版。在我的工作环境中,perl > 5.10 的版本不可用。
我可以毫无困难地传递子程序引用。但是,一旦我尝试将子例程引用传递给线程,该线程似乎并不理解它。
这是我提出的 threadMap 子例程,我相信它的评论对于感兴趣的问答者来说已经足够解释了。
#input: hash with keys L (listref), f (function which can apply to each element of L), and optionally nThreads
#default for nThreads is 50
#divides L into sublists for each thread, then kicks off threads
#each thread applies f to each element of the sublist
#and then returns the result of $f on each item
#output: map{ &$f($_) } @{$L}, but done threadily
sub threadMap{
my %arg = @_;
my ($L,$f,$nThr) = ($arg{L},$arg{f},$arg{nThreads});
my $MAXTHREADS = 50;
if(not defined $nThr or $nThr > $MAXTHREADS){
$nThr = $MAXTHREADS;
}
&log(1,"threadMap: I have f $f");
my @threadLists = &makeSublistsForThreads($L,$nThr);
#in the event that L is less than $nThr, we reduce the number of threads
$nThr = scalar(@threadLists);
my @threads;
my @ret;
for(0 .. $nThr-1){
#invoke the threads in list context
# push @threads, threads->create({'context' => 'list'}, sub{ my ($L,$f) = @_; print "I have L <@$L> and f $f\n"; return (map{ &f($_) } @{$L}) }, ($threadLists[$_],$f) );
push @threads, threads->create({'context' => 'list'}, sub{ my ($L) = @_; print "I have L <@$L> and f $f\n"; return (map{ &f($_) } @{$L}) }, ($threadLists[$_]) );
}
for(@threads){
#each thread returns its items, so we get them back in order
push @ret, $_->join();
}
return @ret;
}
当我运行这个名为“foo”的脚本时,它大约具有以下内容:
my @L = (1 .. 5);
my $f = sub{ my ($i) = @_; return 100*$i; };
print "I have f $f\n";
@out = &threadMap("L"=>\@L,"f"=>$f);
&log(1,"I had input <@L> and output <@out>");
my @realOut = map{ &$f($_) } @L;
&log(1,"Output should be <@realOut>");
我得到这个输出:
我有 f 代码(0xbf3530)
2013 年 7 月 17 日星期三 10:27:49:线程映射:我有 f 代码(0xbf3530)
我有 L <1> 和 f CODE(0x110f100)
线程 1 异常终止:在 /u/jamie /perl/jdPerlLib.pl 第 6037 行调用了未定义的子例程 &main::f。
我有 L <2> 和 f CODE(0x16b3df0)
线程 2 异常终止:在 /u/jamie /perl/jdPerlLib.pl 第 6037 行调用了未定义的子例程 &main::f。
我有 L <3> 和 f CODE(0x1a7d7b0)
线程 3 异常终止:在 /u/jamie/perl/jdPerlLib.pl 第 6037 行调用了未定义的子例程 &main::f。
我有 L <4> 和 f CODE(0x1fbb600)
线程 4 异常终止:在 /u/jamie/perl/jdPerlLib.pl 第 6037 行调用了未定义的子例程 &main::f。
我有 L <5> 和 f CODE(0x7fd5240b78c0)
线程 5 异常终止:未定义的子例程 &main::f 在 /u/jamie/perl/jdPerlLib.pl 第 6037 行调用。
2013 年 7 月 17 日星期三 10:27:49:我输入 <1 2 3 4 5> 并输出 <>
这告诉我函数引用从 foo 到我的 threadMap 子例程的顶部是恒定的,但是一旦它被传递给线程,它就会被更改并变得混乱。为什么是这样?我可以避免吗?
请注意,两者都失败了
#invoke the threads in list context
# push @threads, threads->create({'context' => 'list'}, sub{ my ($L,$f) = @_; print "I have L <@$L> and f $f\n"; return (map{ &f($_) } @{$L}) }, ($threadLists[$_],$f) );
push @threads, threads->create({'context' => 'list'}, sub{ my ($L) = @_; print "I have L <@$L> and f $f\n"; return (map{ &f($_) } @{$L}) }, ($threadLists[$_]) );
和
#invoke the threads in list context
push @threads, threads->create({'context' => 'list'}, sub{ my ($L,$f) = @_; print "I have L <@$L> and f $f\n"; return (map{ &f($_) } @{$L}) }, ($threadLists[$_],$f) );
#push @threads, threads->create({'context' => 'list'}, sub{ my ($L) = @_; print "I have L <@$L> and f $f\n"; return (map{ &f($_) } @{$L}) }, ($threadLists[$_]) );
另外,由于这是我在 stackoverflow 上的第一篇文章,我的问题是否足够清楚,或者过于冗长/不够冗长?