#! perl -slw use strict; use Math::Random::MT qw[ srand rand ]; use Net::CIDR::Lite; use threads qw[ yield ]; use threads::shared; use Thread::Queue; our $WORKERS ||= 10; our $N ||= 1000; sub n2ip { join '.', unpack 'C4', pack 'V', $_[ 0 ] } sub worker { my $tid = threads->tid; srand( $tid ); my( $Q, $sem ) = @_; for( 1 .. $N ) { my $ip = n2ip( int( rand 2**32 ) ); $Q->enqueue( "$tid:$ip" ); ## 1 lock $$sem; ## 2 cond_wait $$sem; ## 3 printf "[$tid] ($_) $ip was %s\n", $$sem ? 'found' : 'not found'; yield; ## 4 } } my $Q = new Thread::Queue; my @sems = map{ my $var :shared; \$var } 0 .. $WORKERS; my @threads = map{ threads->create( \&worker, $Q, $sems[ $_ ] ); } 1 .. $WORKERS; my $CIDR = Net::CIDR::Lite->new( map{ n2ip( int( rand 2**32 ) ) . '/' . ( 1+int( rand 32 ) ) } 1 .. 10 ); print for $CIDR->list; printf "Enter to run threads"; <>; while( threads->list(threads::running) > 1 ) { my( $tid, $ip ) = split ':', $Q->dequeue; print "Got $ip from $tid"; my $found = $CIDR->find( $ip ); $CIDR->add( "$ip/1" ) unless $found; ${ $sems[ $tid ] } = $found; lock ${ $sems[ $tid ] }; cond_signal ${ $sems[ $tid ] }; yield; } $_->join for @threads; #### sub ip2n{ unpack 'V', pack 'C4', split '\.', $_[ 0 ] }