Reputation: 28427
I am trying to get into Perl's use of threads. Reading the documentation I came across the following code:
use threads;
my $thr = threads->create(\&sub1); # Spawn the thread
$thr->detach(); # Now we officially don't care any more
sleep(15); # Let thread run for awhile
sub sub1 {
my $count = 0;
while (1) {
$count++;
print("\$count is $count\n");
sleep(1);
}
}
The goal, it seems, would be to create one thread running sub1 for 15 seconds, and in the mean time print some strings. However, I don't think I understand what's going on at the end of the programme.
First of all, detach()
is defined as follows:
Once a thread is detached, it'll run until it's finished; then Perl will clean up after it automatically.
However, when does the subroutine finish? while(1)
never finishes. Nor do I find any information in sleep()
that it'd cause to break a loop. On top of that, from the point we detach we are 'waiting for the script to finish and then clean it up' for 15 seconds, so if we are waiting for the subroutine to finish, why do we need sleep()
in the main script? The position is awkward to me; it suggests that the main programme sleeps for 15 seconds. But what is the point of that? The main programme (thread?) sleeps while the sub-thread keeps running, but how is the subroutine then terminated?
I guess the idea is that after sleep
-ing is done, the subroutine ends, after which we can detach/clean up. But how is this syntactically clear? Where in the definition of sleep is it said that sleep
terminates a subroutine (and why), and how does it know which one to terminate in case there are more than one threads?
Upvotes: 3
Views: 805
Reputation: 53478
detach
a thread means "I don't care any more", and that does actually mean when your process exits, the thread will error and terminate.
Practically speaking - I don't think you ever want to detach a thread in perl - just add a join
at the end of your code, so it can exit cleanly, and signal it via a semaphore or Thread::Queue
in order to terminate.
$_ -> join for threads -> list;
Will do the trick.
That code example - in my opinion - is a bad example. It's just plain messy to sleep
so a detached thread has a chance to complete, when you could just join
and know that it's finished. This is especially true of perl
threads, which it's deceptive to assume they're lightweight, and so can be trivially started (and detached
). If you're ever spawning enough that the overhead of join
ing them is too high, then you're using perl threads wrong, and probably should fork
instead.
You're quite right - the thread will never terminate, and so you code will always have a 'dirty' exit.
So instead I'd rewrite:
#!/usr/bin/perl
use strict;
use warnings;
use threads;
use threads::shared;
my $run : shared;
$run = 1;
sub sub1 {
my $count = 0;
while ($run) {
$count++;
print("\$count is $count\n");
sleep(1);
}
print "Terminating\n";
}
my $thr = threads->create( \&sub1 ); # Spawn the thread
sleep(15); # Let thread run for awhile
$run = 0;
$thr->join;
That way your main signals the thread to say "I'm done" and waits for it to finish it's current loop.
Upvotes: 2
Reputation: 45659
All threads end when the program ends. The program ends when the main thread ends. The sleep
in the main thread is merely keeping the program running a short time, after which the main thread (therefore the program, therefore all created threads) also end.
So what's up with detach
? It just says "I'm never going to bother joining to this thread, and I don't care what it returns". If you don't either detach
a thread or join
to it, you'd get a warning when the program ends.
Upvotes: 3