Para saber si un número $num
es primo
basta ver si es divisible por uno de los primos
@primes
anteriores a él:
hp@nereida:~/Lperl/src/threads$ cat -n primes-without-threads.pl 1 #!/usr/bin/perl -w 2 use strict; 3 4 my @primes = (2); 5 my $n = (shift || 10); 6 7 NEW_NUMBER: 8 for my $num (3 .. $n) { 9 foreach (@primes) { next NEW_NUMBER if $num % $_ == 0 } 10 print "Found prime $num\n"; 11 push @primes, $num; 12 }
$cur_prime
) con el que está asociado.
Los hilos se estructuran en una topología de pipeline o canal.
El hilo tiene dos canales de comunicación $upstream
y
$downstream
que le comunican con - usando una terminología
jerárquica - el ''hilo padre'' y el ''hilo hijo'' (referenciado
por la variable $kid
). Viendo el flujo de comunicaciones
como una corriente denominaremos a los canales
''río arriba' ($upstream
)
y ''rio abajo'' ($downstream
).
16 sub check_num { 17 my ($upstream, $cur_prime) = @_; 18 my $kid = undef; 19 my $downstream = new Thread::Queue; 20 while (my $num = $upstream->dequeue) { 21 next unless $num % $cur_prime; 22 if ($kid) { 23 $downstream->enqueue($num); 24 } else { 25 print "Found prime $num\n"; 26 $kid = new threads(\&check_num, $downstream, $num); 27 } 28 } 29 $downstream->enqueue(undef) if $kid; 30 $kid->join if $kid; 31 }
El hilo permanece en un bucle escuchando en el canal que viene
del hilo padre (línea 20) hasta que llegue un undef
indicando
el final de la computación. En este último caso
se propaga la señal de finalización (línea 29) y se espera a la finalización
de la thread hija para terminar (línea 30).
El número $num
que acaba de llegar es cribado en la línea 21.
Si supera la criba se envía al hilo hijo.
La condición de la línea 22 comprueba si esta es la primera vez que un número supera la criba de los primos/hilos calculados hasta el momento. Si es así se procede a crear el hilo hijo (líneas 25-26).
El proceso inicial comienza creando la cola (línea 6) y
arrancando el primer hilo que se encargará de la criba por
el primer número primo.
Después procede a insertar los números del 3 al $n
para su cribado corriente abajo:
lhp@nereida:~/Lperl/src/threads$ cat -n primes-using-threads.pl 1 #!/usr/bin/perl -w 2 use strict; 3 use threads; 4 use Thread::Queue; 5 my $n = (shift || 10); 6 my $stream = new Thread::Queue; 7 my $kid = new threads(\&check_num, $stream, 2); 8 9 for my $i (3 .. $n) { 10 $stream->enqueue($i); 11 } 12 13 $stream->enqueue(undef); 14 $kid->join;
Observe que $stream
no tiene el atributo shared
y es, en consecuencia,
una estructura de datos privada. Sin embargo a través de su paso como parámetros
a la subrutina check_num
ejecutada por el hijo queda accesible a este.
Nótese que cada canal de $stream
es compartido por dos hilos
consecutivos.