Wiggins has asked for the wisdom of the Perl Monks concerning the following question:

Once again. Multiple threads, a root thread, and multiple processing threads (looking at emails). I am trying to define a shared Cache::MemoryCache object that holds Message-Ids for all the threads.

Running the supplied prototype code, shows that when it compiles and runs; each thread has a thread-local copy of the cache. I see each thread testing if '2' exists and then setting it's own value.

I have tried 'use vars', 'our', sharing a reference to the object; generally resulting in syntax errors, blessing errors, or local objects.

I have read 'man threads::shared", but won't claim to understand
"Due to problems with Perl’s prototyping, if you want to share a newly created reference, you need to use the "&share([])" and "&share({})" syntax."

#!/usr/bin/perl use threads; use threads::shared; use Cache::MemoryCache; # the history cache my $lockCache:shared; #marks critical section ## Shotgun grammar follows ... hoping something works. #use vars qw($cacheRef); # use vars qw($cache); $cache = new Cache::MemoryCache( ); #our $cache = new Cache::MemoryCache( ); #my $cacheRef =\$cache; #my $cacheRefShar = share($cacheRef); # to tell when all threads are complete # keep from blocking in a join, so we can accept signals my $threadTerm :shared =0; sub checkCache ($); sub setCache ($$); $thr1 = threads->new(\&t,1); $thr2 = threads->new(\&t,10); $thr3 = threads->new(\&t,20); #t (1); sub t { my $id=shift; sleep (int rand(3)); foreach $i (1...10) { print "T$id-$i\n"; my $key = $i + int (rand 3); my $val = checkCache($key); #print "check returned ($val)\n"; if (! defined $val ) { $val = $id+rand(10); #print "T%id-$i $key=$val\n"; setCache ($key, $val); } sleep (int rand (3)); } $threadTerm++; } # to allow future signals to be recognized while ($threadTerm <3) { sleep 2; } $thr1->join; $thr2->join; $thr3->join; ### fini #### sub checkCache ($) { my $key = shift; my $val; { lock $lockCache; #$val= $$cacheRefShar->get( $key ); #Thread 1 terminated abnormally: Can't call method "get" on an u +ndefined value at testCache.pl line 65. $val= $cacheRefShar->get( $key ); #Thread 1 terminated abnormally: Can't call method "get" on unbl +essed reference at testCache.pl line 65. $val= $cache->get( $key ); print "checking $key = ($val)\n"; } return $val; } sub setCache ($$) { my($key, $newval) = @_; { printf "setting $key=$newval\n"; lock $lockCache; $$cacheRefShar->set( $key, $newval, "3 minutes" ); } } sub testAndSet ($$) { #not yet }

Replies are listed 'Best First'.
Re: Threads sharing a Cache::MemoryCache object??
by perrin (Chancellor) on Aug 08, 2008 at 19:30 UTC
    Why not just use a shared hash instead?
      Yes, that is a possibility. I like the cache because it has already figured out/coded how to do the aging process. But that brings up a fundamental question.

      "How well is the Object Oriented(OO) pattern supported within Perl Threads?" There must be a fundamental problem with objects memory management within the "shared" thread.

      While a hash, and thread to do the purging of expired entries might solve this specific problem; what about the general case? Might there be a "thread space" qualifier, just like a "name space" qualifier? This is a reference to the "rootthread::Cache::Cache" object...

        Hi, threads::shared says in its BUG AND LIMITATIONS section:
        It is often not wise to share an object unless the class itself has been written to support sharing. For example, an object's destructor may get called multiple times, once for each thread's scope exit.

        When trying to test your program, use strict; revealed that several variables are used without initialising them (e.g. precious $cacheRefShar). I have fiddled around with shared_clone() and Cache::MemoryCache but to no avail. Again, studying the documentation lead to Cache::SharedMemoryCache which helped a lot. So this works with Perl 5.8.8 (Linux). Here's a draft...