将线程迁移到fork

时间:2013-11-15 12:10:11

标签: multithreading perl

forks::shared应替换threads::shared,但我该如何替换Thread::Queue

如果有可能,我想将以下代码转换为forks?

sub Qfac {

  use threads;
  use threads::shared;
  use Thread::Queue;

  my ($worker, $arrid, $arg) = @_;

  $arrid ||= [];
  $arg   ||= {};

  my %tr;
  my %h :shared;
  my %qe = map { $_ => Thread::Queue->new() } @$arrid;

  for my $id (@$arrid) {
    my $q = $qe{$id};

    $tr{$id} = threads->create($arg, sub{
      my $me = { id => $id };

      while (my $item = $q->dequeue()) {
        $me->{item} = $item;
        eval { $worker->($me, \%h) };
        $me->{err} = $@ if $@;

        my $temp = threads::shared::shared_clone($me);
        {
          lock (%h);
          $h{$id} = $temp;
        }
      }
    });
    $tr{$id}->detach();
  }

  ##
  return sub {
    my $act = shift;

    if    ($act eq "getshared") { return @_ ? @h{@_} : \%h  }
    elsif ($act eq "enqueue")   { $_->enqueue(@_) for values %qe }
    elsif ($act eq "getqe")     { return \%qe }
    elsif ($act eq "gettr")     { return \%tr }
    elsif ($act eq "getssize")  { return threads->get_stack_size()   }
    elsif ($act eq "setssize")  { return threads->set_stack_size(@_) }
    else                        { die "unknown method" }
  };
}

my $worker = sub { 
  my ($me) = @_;
  my $id = $me->{id};

  # $me->{foo} = "bar";
};

my $qf = Qfac($worker, [ 0 .. 10 ]);
# Send work to the thread
$qf->("enqueue", "do_something");

# ...
my $shared = $qf->("getshared");

1 个答案:

答案 0 :(得分:4)

use forks;(及其::shared)是use threads;(及其::shared)的替代品,而Thread :: Queue使用thread :: shared,所以Thread :: Queue将继续正常工作。

use if $ARGV[0], "forks";
use threads;   # No effect under "use forks;"
use Thread::Queue;
my $q = Thread::Queue->new();
print "$$\n";
async {
   print "$$\n";
   print "$_\n" while $_ = $q->dequeue();
};
$q->enqueue($_) for 1..4;
$q->end();
$_->join() for threads->list();

$ perl x.pl 0
6047
6047
1
2
3
4

$ perl x.pl 1
6054
6056
1
2
3
4

(您需要为旧版本添加use forks::shared; for forks。)