develooper Front page | perl.ithreads | Postings from August 2002

Re: Thread-Tie-0.01

From:
Elizabeth Mattijsen
Date:
August 11, 2002 05:06
Subject:
Re: Thread-Tie-0.01
Message ID:
4.2.0.58.20020811134226.03b01af0@mickey.dijkmat.nl
At 12:12 PM 8/11/02 +0100, Nick Ing-Simmons wrote:
> >The Thread::Tie module is a proof-of-concept implementation of another
> >approach to shared variables.  Instead of having shared variables exist
> >in all the threads from which they are accessible, shared variable exist
> >as "normal", unshared variables in a seperate thread.  Only a tied object
> >exists in each thread from which the shared variable is accesible.
>That is actually exactly what threads::shared is supposed to do as well.
>The only difference being that the "separate thread" has a shadowy
>existance

Aha!  So maybe there the "2 other threads were running" message is coming 
from, when you only started one other thread.  Does this shadowy thread run 
always, even if you don't have threads::shared ?


>  and the client threads assume its identity (briefly) to become
>their own server - which was supposed to be an optimization :-(

Maybe it is from a CPU point of view, but it definitely isn't from a memory 
point of view.  Because now in an array each element will need to be tied 
to the shared magic.  In my approach only the object to which the array is 
tied, contains shared elements.  Inside the thread, the array is an array 
just like any other array.  Which saves a lot on magic.  Or am I mistaken 
in this?


> >=item memory usage
> >Shared variables in this approach are truly shared.  The value of a variable
> >only exists once in memory.  This implementation also circumvents the memory
> >leak that currently (threads::shared version 0.90) plagues any shared array
> >or shared hash access.
>As the threads::shared scheme is _supposed_ to be exactly as you describe
>there _should_ be no difference here.

Apart from the huge memory leak that makes it impossible to use shared 
arrays and hashes in a production environment.


> >=item tieing shared variables
> >Because the current implementation uses tie-ing, you can B<not> tie a shared
> >variable.  The same applies for this implementation you might say.  However,
> >it B<is> possible to specify a non-standard tie implementation for use
> >B<within> the thread.  So with this implementation you B<can> C<tie()> a
> >shared variable.  So you B<could> tie a shared hash to a DBM file à la
> >dbmopen() with this module.
>This is still an advantage of your scheme - as the server-thread is
>"visible" its variable can be tied using normal approaches.

Indeed.  You can now have a shared filehandle that is tied using a module 
that doesn't know anything about threads.  Such as a DBM file.

I think the main disadvantages of Thread::Tie (at least under Linux) are:

- threads->yield doesn't seem to yield.
This means you're burning CPU needlessly until your timeslice is over.

- a cond_wait, cond_signal pair is not guaranteed to pass the lock
If you have a thread waiting at a cond_wait, and another thread is doing a 
cond_signal, the thread in cond_wait is _not_ guaranteed to get the lock() 
again.  Not even if you're just using two threads!  For example:

Server thread:

   {lock( $shared );
    warn "server relinquishing control\n";
    cond_wait( $shared );
    warn "server in control again\n";
   }


Client thread:

   {lock( $shared );
    warn "signalling server to act 1\n"
    cond_signal( $shared );
   }
   warn "unlocked 1, waiting for lock 2\n";
   {lock( $shared );
    warn "signalling server to act 2\n"
    cond_signal( $shared );
   }
   warn "unlocked 2\n";

You will see that the client thread is able to gain the lock again after a 
cond_signal (about 75% of the time, under Linux, on my development box) 
before the server thread receives the signal.

Because of this behaviour you need to have a seperate semaphore that is 
checked by the client to see whether the server actually received the 
(previous) signal before preceding.  And of course, when the client sees 
that it gained the lock prematurely, you need to yield().  Something ugly like:

     my $tries;
     AGAIN: while (1) {
         threads->yield if $tries++;
         {lock( $control );
          next AGAIN if defined( $$control );

And of course, at least under Linux, this eats CPU on a massive scale 
because yield() actually doesn't yield.  ;-(


Liz




nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About