On 10/4/06, Zoran Vasiljevic <[EMAIL PROTECTED]> wrote:

On 04.10.2006, at 11:24, Zoran Vasiljevic wrote:

> I think I see where the problem is and will fix that now.

I've fixed that but this opens another discussion.

Basically you wanted to avoid using handles. Then you said,
OK, I can use string names and turn them to handles on as-needed
basis by looking them up in an internal table. Everytime this
lookup happens I need to global lock the table then lookup the
(whatever)handle using it string name.

To avoid that global lock, you change/update the object holding the
string rep with the calculated handle and you count on the fact
that next usage of the same object will avoid having to to the
(costly) lookup.


Right.

And the reason the handle name doesn't have to be looked up again
because we cheat -- the mutexes associated with the handle names live
forever. You can't delete or reassign them. So if you ever find a
pointer to a mutex in one of these handle names, it's valid.


Did you think about such uses:

   ns_mutex lock themutex
   while {} {
      ns_cond wait thecond themutex
   }
   ns_mutex unlock themutex

because here EVERY time you will have to lock the global
lock to get the handle of the "thing", as the "trick" to
save it in the object will not work! The "themutex" or
"thecond" could/will always be different objects if used
this way, so there is no gain.


Hmm...  I think this does work. Here's how I read it:

There are 3 string objects with the value "themutex" in the above
code.  The first time the code runs, there will be 3 global look ups
in the hash table of mutex names to convert the name "themutex" to a
pointer to an actual mutex.

On the first line, in the call to "ns_mutex lock themutex", the last
argument is just a Tcl string object so we have to look up the name in
the mutex hash table. The name doesn't exist, so a new mutex is
allocated, put in the hash table, and a pointer to it is stored in the
Tcl object. The Tcl object is marked as an Address obj type (it's
string rep is not invalidated, we just change the type).

In the call to ns_cond and the last call to ns_mutex, "themutex" is
also just a Tcl string object. So again the mutex hash table has to be
consulted. This time the mutex exists however, so we simply change the
string object to an Address type and store a pointer to the existing
mutex in it.

There are 3 individual Tcl objects, each with the string
representation "themutex". Each now points to exactly the same mutex
in memory.

The second time the code is run, the 3 "themutex" objects retain their
type (Address), so we don't have to look up the name in the mutex hash
table as a pointer to the mutex is stored in the Tcl object itself. We
get access to the mutex with a simple pointer dereference.

So, the premise is that the code will be executed more than once. The
first time will be 'slow', but after that there is no locking at all
to convert the name to an actual mutex.

And it works specifically in the above case because mutex objects are
seperate from Tcl objects which point to them.


If one however does:

  set m themutex
  set t thecond

   ns_mutex lock $m
   while {} {
      ns_cond wait $c $m
   }
   ns_mutex unlock $m

it WILL work. But how are you going to convey this information
to the Tcl programmer??? He's implicitly serializing his app
at the place he does not expect (lookup of the internal hash
table).


Actually, the above might NOT work... :-)

In the above code, $m is a single Tcl string object with the value
"themutex" and, after the first call to "ns_mutex lock $m", we convert
it to a an Address type and point it at a mutex.

There is a single Tcl object pointing to a single mutex, where as in
the original code there were 3 Tcl objects pointing to a single mutex.
There will be a single look up in the mutex hash table, where as in
the original code there will be 3. But only on the first time the code
is run.

The while loop will be 'efficient' because the underlying mutex object
is just a pointer dereference away.

However, what if the whole code block was run in a loop?

At the bottom of the loop, $m is an Address type pointing to our
mutex. At the top of the loop $m is reset:

   set m themutex

The value of the literal "themutex" Tcl string object is copied and
used as the new value of $m. Because the string representation of $m
has changed (even if the actual text is literaly the same, there is no
checking for this), the internal representation is invalidated. i.e.
it is no longer an Address type.

So at the top of the loop we again have to convert m to an Address
type be looking up the name in the mutex hash table. The mutex will
exist in the hash table, but we need to get a pointer to it.

Any operation which looses the type information will break the caching
of the mutex pointer in the object. So, passing the name through an
nsv array or cache will strip the type info.

But I'm having a hard time coming up with real world scenarios where
that might happen...

Reply via email to