package TGrep; use strict; use threads; use Thread::Queue; our $WORKERS = 4; sub g_proxy { my( $code, $Qin, $Qout ) = @_; $Qout->enqueue( $code->() ? $_ : () ) while local $_ = $Qin->dequeue; $Qout->enqueue( undef ); } sub tgrep(&@) { my $workers = $WORKERS; my $code = shift; my( $Qin, $Qout ) = map Thread::Queue->new, 1..2; async( \&g_proxy, $code, $Qin, $Qout )->detach for 1 .. $workers; $Qin->enqueue( map{ ref $_[0] ? @{ $_ } : $_ } @_ ); $Qin->enqueue( (undef) x $workers ); my @results; push @results, $_ while $_ = $Qout->dequeue; return wantarray ? @results : \@results; } sub import { no strict 'refs'; my $pkg = caller; *{ $pkg . '::' . $_ } = *{ $_ } for qw[ tgrep ]; } 1; #### #! perl -slw use strict; use TGrep; use Time::HiRes qw[ time ]; our $N //= 1e3; my $start = time; my @a = tgrep{ $_ % 5 == 0 } [ 1..$N ]; printf "Took %.9f seconds\n", time() -$start; print scalar @a; __END__ C:\test>t-tgrep -N=1e5 Took 3.830074787 seconds 20000 #### $t=time; my @a = grep{ $_%5 == 0 } 1 .. 1e6; print time-$t;; 0.18144702911377