Wednesday, April 13, 2011

Perl - Using threads with shared array of hashes

The following sample code demonstrate sharing of Array of hashes betweenn threads:
use strict;
use warnings;

# Use module thread
use threads ('yield','stack_size' => 64*4096,'exit' => 'threads_only','stringify');

# Use Share
use threads::shared;

# Declare shared array of Files Names
my @FilesList : shared = ();



&RunThreads();
&PrintFilesNames();
###################################################################################
# SubRoutines

sub RunThreads()
{
    # Running thread List
    my @findFilesThreads;

    # Create Threads
    my $dirName = "Directory1";
    my @filesList = ("file11","file12","file13");
    # Launch thread with its argument
    my $thr = threads->create('ThreadFunc',($dirName,@filesList ));
    push(@findFilesThreads,$thr);

    $dirName = "Directory2";
    @filesList = ("file21","file22","file23");
    # Launch thread with its argument
    $thr = threads->create('ThreadFunc',($dirName,@filesList ));
    push(@findFilesThreads,$thr);

    $dirName = "Directory3";
    @filesList = ("file31","file32","file33");
    # Launch thread with its argument
    $thr = threads->create('ThreadFunc',($dirName,@filesList ));
    push(@findFilesThreads,$thr);

    # Wait threads to finish
    foreach (@findFilesThreads)
    {
        my $thread = $_;
        if (defined($thread))
        {
            if ($thread->is_running())
            {
                $thread->join();
            }
            else
            {
                $thread->detach()
            }
        }
    }
}


# The Thread subroutin
sub ThreadFunc()
{
    my ($dirName,@filesName) = @_;

    # Random sleep, So its time the Thread print order will be different
    sleep rand(5);

    print "Add Directory : $dirName\n";
    # Create shread list entries
    my %entry : shared;
    my $dir : shared;
    my @files : shared;
    $entry{directory} = \$dir;
    $entry{files} = \@files;

    # Fill the data
    $entry{directory} = $dirName;
    foreach (@filesName)
    {
        push(@{$entry{files}},$_);
    }

    # lock the shared array
    lock(@FilesList);
    push(@FilesList,\%entry);
    return;
}

sub PrintFilesNames()
{
    print "Directory Tree : \n";
    lock(@FilesList);
    foreach (@FilesList)
    {
        my %entry = %{$_};
        print " Directory name is : $entry{directory}\n";
        print " Files are : \n";
        foreach (@{$entry{files}})
        {
            print "     $_\n";
        }
    }
}
The output of this script will look like (The directories order may change according to the sleep interval):
Add Directory : Directory1
Add Directory : Directory3
Add Directory : Directory2
Directory Tree :
 Directory name is : Directory1
 Files are :
     file11
     file12
     file13
 Directory name is : Directory3
 Files are :
     file31
     file32
     file33
 Directory name is : Directory2
 Files are :
     file21
     file22
     file23

No comments: