multithreading - How do I queue perl subroutines to a thread queue instead of data? -
background:
in reading how multithread perl script, read (from http://perldoc.perl.org/threads.html#bugs-and-limitations)
on systems, frequent , continual creation , destruction of threads can lead ever-increasing growth in memory footprint of perl interpreter. while simple launch threads , ->join() or ->detach() them, long-lived applications, better maintain pool of threads, , reuse them work needed, using queues notify threads of pending work.
my script long-lived; it's pki ldap directory monitoring daemon running. enterprise monitoring solution generate alarm if stops running reason. script check can reach pki ldap directory, validate revocation lists on both.
problem: can find on google shows passing variables (e.g. scalars) thread queue rather subroutine itself... think i'm not understanding how implement thread queue compared how implement thread (without queues).
question 1: how can "maintain pool of threads" avoid perl interpreter eating more , more memory?
question 2: (unrelated while have code posted) there safe amount of sleep @ end of main program don't start thread more once in minute? 60 seems obvious ever cause run more once if loop fast, or perhaps miss minute because of processing time or something?
thanks in advance!
#!/usr/bin/perl use feature ":5.10"; use warnings; use strict; use threads; use proc::daemon; # ### global variables use constant false => 0; use constant true => 1; $app = $0; $continue = true; $sig{term} = sub { $continue = false }; # directory server agent (dsa) info @listofdsas = ( { name => "myself (inbound)", host => "ldap.myco.ca", base => "ou=mydir,o=myco,c=ca", }, { name => "company 2", host => "ldap.comp2.ca", base => "ou=their-dir,o=comp2,c=ca", } ); # ### subroutines sub checkconnections { # runs every 5 minutes (@dsas, $logfile) = @_; # code ldapsearch threads->detach(); } sub validaterevocationlists { # runs every hour on minute xx:55 (@dsas, $logfile) = @_; # code validate crls haven't expired, etc threads->detach(); } # ### main program proc::daemon::init; while ($continue) { ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); # question 1: queues?? if ($min % 5 == 0 || $min == 0) { threads->create(&checkconnections, @listofdsas, "/var/connect.log"); } if ($min % 55 == 0) { threads->create(&validaterevocationlists, @listofdsas, "/var/rls.log"); } sleep 60; # question 2: safer/better way prevent multiple threads being started same check in 1 matching minute? } # term received exit 0; __end__
use threads; use thread::queue 3.01 qw( ); $check_conn_q = thread::queue->new(); $validate_revoke_q = thread::queue->new(); @threads; push @threads, async { while (my $job = $check_conn_q->dequeue()) { check_conn(@$job); } }; push @threads, async { while (my $job = $validate_revoke_q->dequeue()) { validate_revoke(@$job); } }; while ($continue) { ($s,$m,$h,$m,$d,$y) = localtime; $m+=1; $y+=1900; $check_conn_q->enqueue([ @listofdsas, "/var/connect.log" ]) if $m % 5 == 0; $validate_revoke_q->enqueue([ @listofdsas, "/var/rls.log" ]) if $m == 55; sleep 30; } $check_conn_q->end(); $validate_revoke_q->end(); $_->join @threads;
i'm not sure parallelisation needed here. if it's not, use
use list::util qw( min ); sub sleep_until { ($until) = @_; $time = time; return if $time >= $until; sleep($until - $time); } $next_check_conn = $next_validate_revoke = time; while ($continue) { sleep_until min $next_check_conn, $next_validate_revoke; last if !$continue; $time = time; if ($time >= $next_check_conn) { check_conn(@listofdsas, "/var/connect.log"); $next_check_conn = time + 5*60; } if ($time >= $next_validate_revoke) { validate_revoke(@listofdsas, "/var/rls.log"); $next_validate_revoke = time + 60*60; } }