44 lines
1.5 KiB
Perl
44 lines
1.5 KiB
Perl
use Thread 'async';
|
|
use Thread::Queue;
|
|
|
|
sub make_slices {
|
|
my ($n, @avail) = (shift, @{ +shift });
|
|
|
|
my ($q, @part, $gen);
|
|
$gen = sub {
|
|
my $pos = shift; # where to start in the list
|
|
if (@part == $n) {
|
|
# we accumulated enough for a partition, emit them and
|
|
# wait for main thread to pick them up, then back up
|
|
$q->enqueue(\@part, \@avail);
|
|
return;
|
|
}
|
|
|
|
# obviously not enough elements left to make a partition, back up
|
|
return if (@part + @avail < $n);
|
|
|
|
for my $i ($pos .. @avail - 1) { # try each in turn
|
|
push @part, splice @avail, $i, 1; # take one
|
|
$gen->($i); # go deeper
|
|
splice @avail, $i, 0, pop @part; # put it back
|
|
}
|
|
};
|
|
|
|
$q = new Thread::Queue;
|
|
(async{ &$gen; # start the main work load
|
|
$q->enqueue(undef) # signal that there's no more data
|
|
})->detach; # let the thread clean up after itself, not my problem
|
|
|
|
return $q;
|
|
}
|
|
|
|
my $qa = make_slices(4, [ 0 .. 9 ]);
|
|
while (my $a = $qa->dequeue) {
|
|
my $qb = make_slices(2, $qa->dequeue);
|
|
|
|
while (my $b = $qb->dequeue) {
|
|
my $rb = $qb->dequeue;
|
|
print "@$a | @$b | @$rb\n";
|
|
}
|
|
}
|