Help: Threads and queues
am 16.11.2004 11:19:16 von SwartzHi all.
I'm fairly new to Perl (less then 6 months of programming experience).
I'm trying to write a small threaded "proof of concept" application.
Basic ideas:
- there is a number of songs users can listen to,
- each song can only be accessed by one user at a time
- each user can only listen to one song at a time,
This is the part I'm working on right now.
---------------------
#!/usr/bin/perl
use threads;
use threads::shared;
use Thread::Queue;
print "MAIN THREAD: start!\n";
# Hash of songs
%song = ("1" => "Song 1",
"2" => "Song 2",
"3" => "Song 3",
"4" => "Song 4",
"5" => "Song 5",
"6" => "Song 6",
"7" => "Song 7",
"8" => "Song 8");
# 'share' the individual values of %song hash
foreach $key (keys %song) {
share ($song{$key});
}
# spin off 10 threads (a.k.a users)
for ($i = 0; $i < 100 ; $i++) {
$thr = new threads \&login;
}
# Loop through all the threads and 'join' them (credit: perlthrtut)
foreach $thr (threads->list) {
# Don't join the main thread or ourselves
if ($thr->tid && !threads::equal($thr, threads->self)) {
$thr->join;
}
}
print "MAIN THREAD: done!\n";
#######################################################
sub login {
my $ThreadID = threads->self->tid;
print "Thread ${ThreadID}: started\n";
# random song from 1 to 8 for testing
request_song(int rand (8)+1);
}
#######################################################
sub request_song {
my $song_num = shift @_;
my $ThreadID = threads->self->tid;
print "Thread ${ThreadID}: requesting song $song_num...\n";
lock $song{$song_num};
listen_to_song($song_num);
print "Thread ${ThreadID}: finished playing song $song_num\n";
}
#######################################################
sub listen_to_song {
my $song_num = shift @_;
my $song_time = int rand (9)+1;
$ThreadID = threads->self->tid;
print "Thread ${ThreadID}: listening to song $song_num for
$song_time seconds\n";
# pretending to listen to music
sleep $song_time;
}
-----------------------------
What I am trying to do is add a queue for users (or threads for now) who are
trying to request a song that is currently being played ('lock'-ed).
Consequently I wish to display current queue contents at any given time
(although this is not very important right now).
I've ran into a number of questions,
1. How to determine if a particular song is already in use by another thread
and place a request into the queue? Attempting to do something like:
eval (block ($song{$n}))
to check for existing data blocks results in the thread waiting for data to
be unlocked (as expected as I now found out).
2. How to incorporate the queue into my code? One problem being is that I
don't need to enqueue every request for songs, as there will be requests
that can go through now without having to wait for other requests in the
queue ahead of them.
I thought of spinning off a separate thread and a queue for each song,
however it seems like an even more complicated approach.
Any help is appreciated...
Thanks in advance!